Commit the version of Ephoto that has always been the most working and preferred. I will bugfix this version and release it. Any of thousands of rewrites I love to do will have to come for another version somewhere well done the road. Lets just take this and make it solid and release it. Shout out to cedric, bluebugs, captainigloo, k-s, otavio, and any others who contributed to this version.

SVN revision: 60775
This commit is contained in:
Stephen Houston 2011-06-28 22:26:16 +00:00
parent 9967da59b3
commit 962910db6b
33 changed files with 2119 additions and 594 deletions

View File

@ -164,6 +164,7 @@ Makefile
ephoto.spec
data/Makefile
data/desktop/Makefile
data/images/Makefile
data/themes/Makefile
data/themes/default/Makefile
data/themes/default/images/Makefile

View File

@ -1,2 +1,2 @@
MAINTAINERCLEANFILES = Makefile.in Makefile
SUBDIRS = themes desktop
SUBDIRS = desktop images themes

20
data/images/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
MAINTAINERCLEANFILES = Makefile.in Makefile
IMAGES = \
back.png \
back_grid.png \
first.png \
folder.png \
forward.png \
grid.png \
last.png \
single.png \
slideshow.png \
up.png \
zoom-fit.png \
zoom-in.png \
zoom-original.png \
zoom-out.png
imagesdir = $(pkgdatadir)/images
images_DATA = $(IMAGES)

BIN
data/images/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
data/images/back_grid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
data/images/first.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
data/images/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
data/images/forward.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
data/images/grid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
data/images/last.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
data/images/single.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
data/images/slideshow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
data/images/up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
data/images/zoom-fit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
data/images/zoom-in.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
data/images/zoom-out.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -3,183 +3,119 @@ external: "elm";
}
collections {
images
{
}
group
{
name: "ephoto/layout/single/browser";
parts
{
part
{
name: "ephoto.swallow.content";
group { name: "elm/layout/ephoto/orient";
parts {
part { name: "elm.swallow.content";
type: SWALLOW;
description
{
rel1.relative: 0.0 0.0;
rel1.offset: 0 0;
rel2.relative: 1.0 1.0;
rel2.offset: -1 -1;
description { state: "default" 0.0;
}
}
}
}
group
{
name: "elm/layout/ephoto/orient";
parts
{
part
{
name: "elm.swallow.content";
type: SWALLOW;
description
{
state: "default" 0.0;
}
description
{
state: "rotate_0" 0.0;
description { state: "rotate_0" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation.z: 0;
}
}
description
{
state: "rotate_90" 0.0;
description { state: "rotate_90" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation.z: 90;
}
}
description
{
state: "rotate_180" 0.0;
description { state: "rotate_180" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation.z: 180;
}
}
description
{
state: "rotate_270" 0.0;
description { state: "rotate_270" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation.z: 270;
}
}
description
{
state: "flip_horiz" 0.0;
description { state: "flip_horiz" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation.y: 180;
}
}
description
{
state: "flip_vert" 0.0;
description { state: "flip_vert" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation.x: 180;
}
}
description
{
state: "flip_horiz_90" 0.0;
description { state: "flip_horiz_90" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation
{
rotation {
z: 90;
y: 180;
}
}
}
description
{
state: "flip_vert_90" 0.0;
description { state: "flip_vert_90" 0.0;
inherit: "default" 0.0;
map
{
map {
on: 1;
rotation
{
rotation {
z: 90;
x: 180;
}
}
}
}
programs
{
program
{
programs {
program {
signal: "state,rotate,0";
source: "ephoto";
action: STATE_SET "rotate_0" 0.0;
target: "elm.swallow.content";
}
program
{
program {
signal: "state,rotate,90";
source: "ephoto";
action: STATE_SET "rotate_90" 0.0;
target: "elm.swallow.content";
}
program
{
program {
signal: "state,rotate,180";
source: "ephoto";
action: STATE_SET "rotate_180" 0.0;
target: "elm.swallow.content";
}
program
{
program {
signal: "state,rotate,270";
source: "ephoto";
action: STATE_SET "rotate_270" 0.0;
target: "elm.swallow.content";
}
program
{
program {
signal: "state,flip,horiz";
source: "ephoto";
action: STATE_SET "flip_horiz" 0.0;
target: "elm.swallow.content";
}
program
{
program {
signal: "state,flip,vert";
source: "ephoto";
action: STATE_SET "flip_vert" 0.0;
target: "elm.swallow.content";
}
program
{
program {
signal: "state,flip,horiz,90";
source: "ephoto";
action: STATE_SET "flip_horiz_90" 0.0;
target: "elm.swallow.content";
}
program
{
program {
signal: "state,flip,vert,90";
source: "ephoto";
action: STATE_SET "flip_vert_90" 0.0;
@ -188,24 +124,479 @@ collections {
}
}
}
group
{
name: "ephoto,thumb,grid";
parts
{
part
{
name: "ephoto.swallow.content.thumb";
group { name: "elm/gengrid/item/ephoto-album-preview/default";
data.item: "labels" "elm.text";
data.item: "icons" "elm.swallow.icon.1 elm.swallow.icon.2 elm.swallow.icon.3";
data.item: "states" "have_files";
images {
image: "bt_sm_base1.png" COMP;
image: "bt_sm_shine.png" COMP;
image: "bt_sm_hilight.png" COMP;
image: "directory-512.png" COMP;
}
parts {
part { name: "event";
type: RECT;
repeat_events: 1;
description { state: "default" 0.0;
color: 0 0 0 0;
}
}
part { name: "bg";
clip_to: "disclip";
mouse_events: 0;
description { state: "default" 0.0;
visible: 0;
color: 255 255 255 0;
rel1.offset: -3 -3;
rel2.offset: 2 2;
image {
normal: "bt_sm_base1.png";
border: 6 6 6 6;
middle: SOLID;
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
color: 255 255 255 255;
}
}
part { name: "image";
type: IMAGE;
mouse_events: 0;
description { state: "default" 0.0;
aspect_preference: BOTH;
aspect: 1.0 1.0;
image.normal: "directory-512.png";
rel2 {
to_y: "elm.text";
relative: 1.0 0.0;
offset: -1 -2;
}
}
}
part { name: "have-files-clipper";
type: RECT;
description { state: "default" 0.0;
color: 255 255 255 0;
visible: 0;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
color: 255 255 255 255;
visible: 1;
}
}
part { name: "icon_box_margin";
type: RECT;
mouse_events: 0;
clip_to: "have-files-clipper";
description { state: "default" 0.0;
color: 255 255 255 0;
rel1 {
to: "icon_box";
offset: -1 -1;
}
rel2 {
to: "icon_box";
offset: 0 0;
}
}
}
part { name: "icon_box";
type: RECT;
mouse_events: 0;
clip_to: "have-files-clipper";
description { state: "default" 0.0;
color: 255 255 255 0;
align: 1.0 1.0;
min: 32 32;
rel1 {
to: "image";
relative: 0.0 0.0;
offset: 0 20;
}
rel2 {
to: "image";
relative: 1.0 1.0;
offset: -1 -1;
}
}
}
part { name: "elm.swallow.icon.1";
type: SWALLOW;
mouse_events: 1;
description
{
state: "default" 0.0;
rel1.relative : 0.0 0.0;
rel1.offset : 0 0;
rel2.relative : 1.0 1.0;
rel2.offset : -1 -1;
}
mouse_events: 0;
clip_to: "have-files-clipper";
description { state: "default" 0.0;
color: 255 0 0 255;
map {
on: 0;
rotation {
z: 0;
}
}
rel1 {
relative: 0.2 0.2;
to: "icon_box";
}
rel2 {
relative: 0.8 0.8;
offset: -1 -1;
to: "icon_box";
}
}
}
part { name: "elm.swallow.icon.2";
type: SWALLOW;
mouse_events: 0;
clip_to: "have-files-clipper";
description { state: "default" 0.0;
color: 255 0 0 255;
map {
on: 1;
rotation {
z: 15;
}
}
rel1 {
relative: 0.2 0.2;
to: "icon_box";
}
rel2 {
relative: 0.8 0.8;
offset: -1 -1;
to: "icon_box";
}
}
}
part { name: "elm.swallow.icon.3";
type: SWALLOW;
mouse_events: 0;
clip_to: "have-files-clipper";
description { state: "default" 0.0;
color: 255 0 0 255;
map {
on: 1;
rotation {
z: -15;
}
}
rel1 {
relative: 0.2 0.2;
to: "icon_box";
}
rel2 {
relative: 0.8 0.8;
offset: -1 -1;
to: "icon_box";
}
}
}
part { name: "elm.text";
clip_to: "disclip";
type: TEXT;
effect: SOFT_SHADOW;
mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1 {
relative: 0.0 1.0;
offset: 20 -30;
}
rel2 {
relative: 1.0 1.0;
offset: -21 -15;
}
color: 0 0 0 255;
color3: 0 0 0 0;
text {
font: "Sans";
size: 10;
min: 0 1;
align: 0.5 0.0;
text_class: "grid_item";
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
color: 255 255 255 255;
}
}
part { name: "fg1";
clip_to: "disclip";
mouse_events: 0;
description { state: "default" 0.0;
visible: 0;
color: 255 255 255 0;
rel1.offset: -3 -3;
rel2 {
relative: 1.0 0.5;
offset: 2 -1;
}
image {
normal: "bt_sm_hilight.png";
border: 6 6 6 0;
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
color: 255 255 255 255;
}
}
part { name: "fg2";
clip_to: "disclip";
mouse_events: 0;
description { state: "default" 0.0;
visible: 0;
color: 255 255 255 0;
rel1.offset: -3 -3;
rel2.offset: 2 2;
image {
normal: "bt_sm_shine.png";
border: 6 6 6 0;
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
color: 255 255 255 255;
}
}
part { name: "disclip";
type: RECT;
description { state: "default" 0.0;
rel1.to: "bg";
rel2.to: "bg";
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
color: 255 255 255 64;
}
}
}
programs {
program { name: "load";
signal: "load";
// script {
// new Float:val;
// custom_state(PART:"elm.swallow.icon.3", "default", 0.0);
// custom_state(PART:"elm.swallow.icon.1", "default", 0.0);
// val = randf();
// val = 40 * val - 20;
// set_state_val(PART:"elm.swallow.icon.3", STATE_MAP_ROT_Z, val);
// val = randf();
// val = 40 * val - 20;
// set_state_val(PART:"elm.swallow.icon.1", STATE_MAP_ROT_Z, val);
//set_state(PART:"elm.swallow.icon.1", "custom", 0.0);
// set_state(PART:"elm.swallow.icon.3", "custom", 0.0);
//}
}
program { name: "go_active";
signal: "elm,state,selected";
source: "elm";
action: STATE_SET "selected" 0.0;
target: "bg";
target: "fg1";
target: "fg2";
target: "elm.text";
}
program { name: "go_passive";
signal: "elm,state,unselected";
source: "elm";
action: STATE_SET "default" 0.0;
target: "bg";
target: "fg1";
target: "fg2";
target: "elm.text";
transition: LINEAR 0.1;
}
program { name: "go_disabled";
signal: "elm,state,disabled";
source: "elm";
action: STATE_SET "disabled" 0.0;
target: "disclip";
}
program { name: "go_enabled";
signal: "elm,state,enabled";
source: "elm";
action: STATE_SET "default" 0.0;
target: "disclip";
}
program {
signal: "elm,state,have_files,active";
source: "elm";
action: STATE_SET "visible" 0.0;
target: "have-files-clipper";
}
}
}
group { name: "elm/gengrid/item/ephoto-up/default";
data.item: "labels" "elm.text";
images {
image: "bt_sm_base1.png" COMP;
image: "bt_sm_shine.png" COMP;
image: "bt_sm_hilight.png" COMP;
image: "directory-up-512.png" COMP;
}
parts {
part { name: "event";
type: RECT;
repeat_events: 1;
description { state: "default" 0.0;
color: 0 0 0 0;
}
}
part { name: "bg";
clip_to: "disclip";
mouse_events: 0;
description { state: "default" 0.0;
visible: 0;
color: 255 255 255 0;
rel1.offset: -3 -3;
rel2.offset: 2 2;
image {
normal: "bt_sm_base1.png";
border: 6 6 6 6;
middle: SOLID;
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
color: 255 255 255 255;
}
}
part { name: "image";
type: IMAGE;
mouse_events: 0;
description { state: "default" 0.0;
aspect_preference: BOTH;
aspect: 1.0 1.0;
image.normal: "directory-up-512.png";
rel2 {
to_y: "elm.text";
relative: 1.0 0.0;
offset: -1 -2;
}
}
}
part { name: "elm.text";
clip_to: "disclip";
type: TEXT;
effect: SOFT_SHADOW;
mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1 {
relative: 0.0 1.0;
offset: 20 -30;
}
rel2 {
relative: 1.0 1.0;
offset: -21 -15;
}
color: 0 0 0 255;
color3: 0 0 0 0;
text {
font: "Sans";
size: 10;
min: 0 1;
align: 0.5 0.0;
text_class: "grid_item";
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
color: 255 255 255 255;
}
}
part { name: "fg1";
clip_to: "disclip";
mouse_events: 0;
description { state: "default" 0.0;
visible: 0;
color: 255 255 255 0;
rel1.offset: -3 -3;
rel2 {
relative: 1.0 0.5;
offset: 2 -1;
}
image {
normal: "bt_sm_hilight.png";
border: 6 6 6 0;
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
color: 255 255 255 255;
}
}
part { name: "fg2";
clip_to: "disclip";
mouse_events: 0;
description { state: "default" 0.0;
visible: 0;
color: 255 255 255 0;
rel1.offset: -3 -3;
rel2.offset: 2 2;
image {
normal: "bt_sm_shine.png";
border: 6 6 6 0;
}
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
color: 255 255 255 255;
}
}
part { name: "disclip";
type: RECT;
description { state: "default" 0.0;
rel1.to: "bg";
rel2.to: "bg";
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
color: 255 255 255 64;
}
}
}
programs {
program { name: "go_active";
signal: "elm,state,selected";
source: "elm";
action: STATE_SET "selected" 0.0;
target: "bg";
target: "fg1";
target: "fg2";
target: "elm.text";
}
program { name: "go_passive";
signal: "elm,state,unselected";
source: "elm";
action: STATE_SET "default" 0.0;
target: "bg";
target: "fg1";
target: "fg2";
target: "elm.text";
transition: LINEAR 0.1;
}
program { name: "go_disabled";
signal: "elm,state,disabled";
source: "elm";
action: STATE_SET "disabled" 0.0;
target: "disclip";
}
program { name: "go_enabled";
signal: "elm,state,enabled";
source: "elm";
action: STATE_SET "default" 0.0;
target: "disclip";
}
}
}

View File

@ -1,2 +1,9 @@
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = \
thumb_shadow.png \
bt_sm_base1.png \
bt_sm_shine.png \
bt_sm_hilight.png \
directory-512.png \
directory-up-512.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -17,9 +17,10 @@ _sources = \
ephoto.c \
ephoto_main.c \
ephoto_config.c \
ephoto_list_browser.c \
ephoto_directory_thumb.c \
ephoto_thumb_browser.c \
ephoto_single_browser.c
ephoto_single_browser.c \
ephoto_slideshow.c
_libs = @ELEMENTARY_LIBS@ @EFREET_MIME_LIBS@ @EIO_LIBS@ @EXIF_LIBS@ @EET_LIBS@

View File

@ -29,7 +29,7 @@ elm_main(int argc, char **argv)
elm_need_ethumb();
elm_init(argc, argv);
elm_theme_extension_add(NULL, THEME_FILE);
elm_theme_extension_add(NULL, PACKAGE_DATA_DIR"/themes/default/ephoto.edj");
if (!efreet_mime_init())
fprintf(stderr, "Could not init efreet_mime!\n");

View File

@ -24,7 +24,6 @@
#define THEME_FILE PACKAGE_DATA_DIR"/themes/default/ephoto.edj"
/*Typedefs*/
typedef struct _Ephoto_Config Ephoto_Config;
typedef struct _Ephoto Ephoto;
typedef struct _Ephoto_Entry Ephoto_Entry;
@ -33,50 +32,48 @@ typedef struct _Ephoto_Event_Entry_Create Ephoto_Event_Entry_Create;
typedef enum _Ephoto_State Ephoto_State;
typedef enum _Ephoto_Orient Ephoto_Orient;
/*Main Gui Functions/Callbacks*/
Evas_Object *ephoto_window_add(const char *path);
void ephoto_title_set(Ephoto *ephoto, const char *title);
void ephoto_thumb_size_set(Ephoto *ephoto, int size);
Evas_Object *ephoto_thumb_add(Ephoto *ephoto, Evas_Object *parent, const char *path);
void ephoto_thumb_path_set(Evas_Object *o, const char *path);
Evas_Object *ephoto_list_icon_add(Ephoto *ephoto, Evas_Object *parent, const char *standard);
void ephoto_directory_set(Ephoto *ephoto, const char *path);
void ephoto_promote_list_browser(Ephoto *ephoto);
void ephoto_promote_thumb_browser(Ephoto *ephoto);
void ephoto_promote_single_browser(Ephoto *ephoto, Ephoto_Entry *e);
/*Get the exif orientation of a JPEG*/
Ephoto_Orient ephoto_file_orient_get(const char *path);
/*Config Functions/Callbacks*/
Eina_Bool ephoto_config_init(Ephoto *em);
void ephoto_config_save(Ephoto *em, Eina_Bool instant);
void ephoto_config_free(Ephoto *em);
/*List Browser*/
Evas_Object *ephoto_list_browser_add(Ephoto *ephoto, Evas_Object *parent);
void ephoto_list_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry);
/*Thumb Browser*/
Evas_Object *ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent);
void ephoto_thumb_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry);
/*Single Browser*/
Evas_Object *ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent);
void ephoto_single_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry);
void ephoto_single_browser_path_pending_set(Evas_Object *obj, const char *path);
/* smart callbacks called:
* "back" - the user want to go back to the previous screen.
*/
Evas_Object *ephoto_slideshow_add(Ephoto *ephoto, Evas_Object *parent);
void ephoto_slideshow_entry_set(Evas_Object *obj, Ephoto_Entry *entry);
/* smart callbacks called:
* "back" - the user want to go back to the previous screen.
*/
Evas_Object *ephoto_directory_thumb_add(Evas_Object *parent, Ephoto_Entry *e);
Evas_Object *ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent);
/* smart callbacks called:
* "selected" - an item in the thumb browser is selected. The selected Ephoto_Entry is passed as event_info argument.
*/
/*Ephoto View*/
enum _Ephoto_State
{
EPHOTO_STATE_LIST,
EPHOTO_STATE_THUMB,
EPHOTO_STATE_SINGLE,
EPHOTO_STATE_SLIDESHOW
};
/*Ephoto Orientation*/
enum _Ephoto_Orient
enum _Ephoto_Orient /* matches with exif orientation tag */
{
EPHOTO_ORIENT_0 = 1,
EPHOTO_ORIENT_FLIP_HORIZ = 2,
@ -88,40 +85,41 @@ enum _Ephoto_Orient
EPHOTO_ORIENT_270 = 8
};
/*Ephoto Config*/
/* TODO: split into window & global config, allow multi window
*
* This also requires single instance, as 2 instances changing the
* same configuration will lead to problems.
*
* Single instance is better done as DBus, using FDO standard methods.
*/
struct _Ephoto_Config
{
int config_version;
int autohide_toolbar;
int best_fit_images;
const char *editor;
double slideshow_timeout;
const char *slideshow_transition;
/* these should be per-window */
int thumb_size;
int thumb_gen_size;
double slideshow_timeout;
const char *directory;
const char *slideshow_transition;
};
/*Ephoto Main*/
struct _Ephoto
{
Evas_Object *win;
Evas_Object *bg;
Evas_Object *overlay;
Evas_Object *layout;
Evas_Object *edje;
Evas_Object *pager;
Evas_Object *help_but;
Evas_Object *list_browser;
Evas_Object *thumb_browser;
Evas_Object *single_browser;
Evas_Object *slideshow;
Eina_List *entries;
Eina_List *thumbs;
Eina_List *dirs;
Eina_List *thumbs; /* live thumbs that need to be regenerated on changes */
int thumb_gen_size;
int thumb_gen_size; /* pending value for thumb_regen */
struct {
Ecore_Timer *thumb_regen;
} timer;
@ -137,16 +135,18 @@ struct _Ephoto
Ephoto_Config *config;
};
/*Ephoto Entry*/
struct _Ephoto_Entry
{
const char *path;
const char *basename;
const char *basename; /* pointer inside path */
const char *label;
Ephoto *ephoto;
Elm_Gengrid_Item *item;
Elm_Genlist_Item *list_item;
Eina_List *free_listeners;
Eina_List *dir_files; /* if dir, here contain files with preview */
Eina_Bool dir_files_checked : 1;
Eina_Bool is_dir : 1;
Eina_Bool is_up : 1;
};
struct _Ephoto_Event_Entry_Create
@ -154,24 +154,21 @@ struct _Ephoto_Event_Entry_Create
Ephoto_Entry *entry;
};
/*Ephoto Entry Functions/Callbacks*/
Ephoto_Entry *ephoto_entry_new(Ephoto *ephoto, const char *path, const char *label);
void ephoto_entry_free(Ephoto_Entry *entry);
void ephoto_entry_free_listener_add(Ephoto_Entry *entry, void (*cb)(void *data, const Ephoto_Entry *entry), const void *data);
void ephoto_entry_free_listener_del(Ephoto_Entry *entry, void (*cb)(void *data, const Ephoto_Entry *entry), const void *data);
void ephoto_entries_free(Ephoto *ephoto);
/*Ephoto Logging*/
extern int __log_domain;
#define DBG(...) EINA_LOG_DOM_DBG(__log_domain, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(__log_domain, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(__log_domain, __VA_ARGS__)
/*Checks to determine if a file is an image*/
static inline Eina_Bool
_ephoto_eina_file_direct_info_image_useful(const Eina_File_Direct_Info *info)
{
const char *bname, *ext;
const char /* *type, */ *bname, *ext;
bname = info->path + info->name_start;
if (bname[0] == '.') return EINA_FALSE;
@ -185,23 +182,17 @@ _ephoto_eina_file_direct_info_image_useful(const Eina_File_Direct_Info *info)
ext++;
if ((strcasecmp(ext, "jpg") == 0) ||
(strcasecmp(ext, "jpeg") == 0) ||
(strcasecmp(ext, "png") == 0) ||
(strcasecmp(ext, "svg") == 0) ||
(strcasecmp(ext, "svgz") == 0) ||
(strcasecmp(ext, "bmp") == 0) ||
(strcasecmp(ext, "dib") == 0) ||
(strcasecmp(ext, "tiff") == 0) ||
(strcasecmp(ext, "tif") == 0) ||
(strcasecmp(ext, "psd") == 0))
(strcasecmp(ext, "png") == 0))
return EINA_TRUE;
}
return EINA_FALSE;
/* seems that this does not play nice with threads */
//if (!(type = efreet_mime_type_get(info->path))) return EINA_FALSE;
//return strncmp(type, "image/", sizeof("image/") - 1) == 0;
}
/*Ephoto Event Handlers*/
extern int EPHOTO_EVENT_ENTRY_CREATE_DIR;
extern int EPHOTO_EVENT_ENTRY_CREATE_THUMB;
extern int EPHOTO_EVENT_ENTRY_CREATE;
extern int EPHOTO_EVENT_POPULATE_START;
extern int EPHOTO_EVENT_POPULATE_END;
extern int EPHOTO_EVENT_POPULATE_ERROR;

View File

@ -1,6 +1,6 @@
#include "ephoto.h"
#define CONFIG_VERSION 6
#define CONFIG_VERSION 5
static int _ephoto_config_load(Ephoto *ephoto);
static Eina_Bool _ephoto_on_config_save(void *data);
@ -13,42 +13,52 @@ ephoto_config_init(Ephoto *ephoto)
{
Eet_Data_Descriptor_Class eddc;
if (!eet_eina_stream_data_descriptor_class_set
(&eddc, sizeof (eddc), "Ephoto_Config", sizeof(Ephoto_Config)))
if (!eet_eina_stream_data_descriptor_class_set(&eddc, sizeof (eddc), "Ephoto_Config", sizeof(Ephoto_Config)))
{
ERR("Unable to create the config data descriptor!");
return EINA_FALSE;
}
if (!edd) edd = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "config_version", config_version, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "autohide_toolbar", autohide_toolbar, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "best_fit_images", best_fit_images, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "thumb_gen_size", thumb_gen_size, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "thumb_size", thumb_size, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "slideshow_timeout", slideshow_timeout, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "directory", directory, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC
(edd, Ephoto_Config, "slideshow_transition", slideshow_transition, EET_T_STRING);
#undef T
#undef D
#define T Ephoto_Config
#define D edd
#define C_VAL(edd, type, member, dtype) EET_DATA_DESCRIPTOR_ADD_BASIC(edd, type, #member, member, dtype)
C_VAL(D, T, config_version, EET_T_INT);
C_VAL(D, T, thumb_size, EET_T_INT);
C_VAL(D, T, thumb_gen_size, EET_T_INT);
C_VAL(D, T, directory, EET_T_STRING);
C_VAL(D, T, slideshow_timeout, EET_T_DOUBLE);
C_VAL(D, T, slideshow_transition, EET_T_STRING);
C_VAL(D, T, editor, EET_T_STRING);
switch (_ephoto_config_load(ephoto))
{
case 0:
/* Start a new config */
ephoto->config->config_version = CONFIG_VERSION;
ephoto->config->autohide_toolbar = 0;
ephoto->config->best_fit_images = 0;
ephoto->config->thumb_gen_size = 256;
ephoto->config->thumb_size = 256;
ephoto->config->thumb_gen_size = 256;
ephoto->config->slideshow_timeout = 4.0;
ephoto->config->slideshow_transition = eina_stringshare_add("fade");
ephoto->config->editor = eina_stringshare_add("gimp %s");
break;
case -1:
/* Incremental additions */
if (ephoto->config->config_version < 2)
{
ephoto->config->slideshow_timeout = 4.0;
ephoto->config->slideshow_transition = eina_stringshare_add("fade");
}
if (ephoto->config->config_version < 3)
ephoto->config->editor = eina_stringshare_add("gimp %s");
if (ephoto->config->config_version < 5)
ephoto->config->thumb_gen_size = 256;
ephoto->config->config_version = CONFIG_VERSION;
break;
default:
@ -102,25 +112,16 @@ _ephoto_config_load(Ephoto *ephoto)
ephoto->config = eet_data_read(ef, edd, "config");
eet_close(ef);
if (!ephoto->config)
{
DBG("Warning! No configuration found! Writing a new"
"default configuration!\n");
return 0;
}
else if (ephoto->config->config_version > CONFIG_VERSION)
if (ephoto->config->config_version > CONFIG_VERSION)
{
ephoto_config_free(ephoto);
ephoto->config = calloc(1, sizeof(Ephoto_Config));
return 0;
}
else if (ephoto->config->config_version < CONFIG_VERSION)
{
ephoto_config_free(ephoto);
ephoto->config = calloc(1, sizeof(Ephoto_Config));
return 0;
}
if (ephoto->config->config_version < CONFIG_VERSION)
return -1;
return 1;
}

View File

@ -0,0 +1,176 @@
#include "ephoto.h"
typedef struct _Ephoto_Directory_Thumb Ephoto_Directory_Thumb;
struct _Ephoto_Directory_Thumb
{
Eio_File *ls;
Eina_List *objs;
Ephoto_Entry *entry;
Eina_Bool canceled:1;
};
static Eina_Hash *_pending_dirs = NULL;
static void
_entry_free(void *data, const Ephoto_Entry *entry __UNUSED__)
{
Ephoto_Directory_Thumb *dt = data;
dt->entry = NULL;
}
static void
_ephoto_directory_thumb_free(Ephoto_Directory_Thumb *dt)
{
if (dt->entry)
{
ephoto_entry_free_listener_del(dt->entry, _entry_free, dt);
eina_hash_del(_pending_dirs, dt->entry->path, dt);
dt->entry = NULL;
}
if (dt->ls)
{
dt->canceled = EINA_TRUE;
eio_file_cancel(dt->ls);
return;
}
free(dt);
if (_pending_dirs)
{
if (!eina_hash_population(_pending_dirs))
{
eina_hash_free(_pending_dirs);
_pending_dirs = NULL;
}
}
}
static void
_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
Ephoto_Directory_Thumb *dt = data;
dt->objs = eina_list_remove(dt->objs, obj);
if (!dt->objs)
{
dt->canceled = EINA_TRUE;
_ephoto_directory_thumb_free(dt);
}
}
static Eina_Bool
_populate_filter(void *data __UNUSED__, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info)
{
return _ephoto_eina_file_direct_info_image_useful(info);
}
static void
_populate_end(void *data, Eio_File *handler __UNUSED__)
{
Ephoto_Directory_Thumb *dt = data;
Evas_Object *obj;
dt->ls = NULL;
EINA_LIST_FREE(dt->objs, obj)
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL, _obj_del, dt);
if (dt->entry)
{
dt->entry->dir_files_checked = EINA_TRUE;
if ((dt->entry->item) && (!dt->canceled))
elm_gengrid_item_update(dt->entry->item);
}
_ephoto_directory_thumb_free(dt);
}
static void
_populate_error(void *data, Eio_File *handler, int error)
{
Ephoto_Directory_Thumb *dt = data;
if (error) ERR("could not populate: %s", strerror(error));
_populate_end(dt, handler);
}
static void
_populate_main(void *data, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info)
{
Ephoto_Directory_Thumb *dt = data;
Evas_Object *obj;
const char *file;
if (!dt->objs) return;
if (!dt->entry) return;
obj = dt->objs->data;
file = eina_stringshare_add(info->path);
DBG("populate thumbnail %p with path '%s'", obj, file);
dt->objs = eina_list_remove_list(dt->objs, dt->objs);
dt->entry->dir_files = eina_list_append(dt->entry->dir_files, file);
ephoto_thumb_path_set(obj, file);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL, _obj_del, dt);
if ((!dt->objs) && (dt->ls))
{
eio_file_cancel(dt->ls);
dt->ls = NULL;
}
}
Evas_Object *
ephoto_directory_thumb_add(Evas_Object *parent, Ephoto_Entry *entry)
{
Ephoto_Directory_Thumb *dt;
Evas_Object *obj;
if (_pending_dirs)
dt = eina_hash_find(_pending_dirs, entry->path);
else
{
dt = NULL;
_pending_dirs = eina_hash_stringshared_new(NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(_pending_dirs, NULL);
}
obj = ephoto_thumb_add(entry->ephoto, parent, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
if (!dt)
{
dt = calloc(1, sizeof(Ephoto_Directory_Thumb));
if (!dt)
{
ERR("could not allocate memory for Ephoto_Directory_Thumb");
evas_object_del(obj);
return NULL;
}
ephoto_entry_free_listener_add(entry, _entry_free, dt);
dt->entry = entry;
dt->ls = eio_file_direct_ls(entry->path,
_populate_filter,
_populate_main,
_populate_end,
_populate_error,
dt);
if (!dt->ls)
{
ERR("could not create eio_file_direct_ls(%s)", entry->path);
evas_object_del(obj);
free(dt);
return NULL;
}
eina_hash_add(_pending_dirs, entry->path, dt);
DBG("start thread to lookup inside '%s' for thumbnails.", entry->path);
}
else
DBG("thread already started, wait for thumbnails in '%s'", entry->path);
dt->objs = eina_list_append(dt->objs, obj);
evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _obj_del, dt);
return obj;
}

View File

@ -1,7 +1,6 @@
#include "ephoto.h"
int EPHOTO_EVENT_ENTRY_CREATE_DIR = 0;
int EPHOTO_EVENT_ENTRY_CREATE_THUMB = 0;
int EPHOTO_EVENT_ENTRY_CREATE = 0;
int EPHOTO_EVENT_POPULATE_START = 0;
int EPHOTO_EVENT_POPULATE_END = 0;
int EPHOTO_EVENT_POPULATE_ERROR = 0;
@ -21,18 +20,93 @@ _ephoto_state_set(Ephoto *ephoto, Ephoto_State state)
}
static void
_back_clicked(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
_ephoto_thumb_browser_show(Ephoto *ephoto, Ephoto_Entry *entry)
{
DBG("entry '%s'", entry ? entry->path : "");
ephoto_single_browser_entry_set(ephoto->single_browser, NULL);
ephoto_slideshow_entry_set(ephoto->slideshow, NULL);
elm_pager_content_promote(ephoto->pager, ephoto->thumb_browser);
_ephoto_state_set(ephoto, EPHOTO_STATE_THUMB);
if ((entry) && (entry->item)) elm_gengrid_item_bring_in(entry->item);
}
static void
_ephoto_single_browser_show(Ephoto *ephoto, Ephoto_Entry *entry)
{
DBG("entry '%s'", entry->path);
ephoto_single_browser_entry_set(ephoto->single_browser, entry);
elm_pager_content_promote(ephoto->pager, ephoto->single_browser);
_ephoto_state_set(ephoto, EPHOTO_STATE_SINGLE);
}
static void
_ephoto_slideshow_show(Ephoto *ephoto, Ephoto_Entry *entry)
{
DBG("entry '%s'", entry->path);
ephoto_slideshow_entry_set(ephoto->slideshow, entry);
elm_pager_content_promote(ephoto->pager, ephoto->slideshow);
_ephoto_state_set(ephoto, EPHOTO_STATE_SLIDESHOW);
}
static void
_ephoto_single_browser_back(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Ephoto *ephoto = data;
switch (ephoto->state)
{
case EPHOTO_STATE_SINGLE : ephoto_promote_thumb_browser(ephoto); break;
case EPHOTO_STATE_THUMB : ephoto_promote_list_browser(ephoto); break;
case EPHOTO_STATE_LIST : break;
default : break;
Ephoto_Entry *entry = event_info;
_ephoto_thumb_browser_show(ephoto, entry);
}
ephoto_title_set(ephoto, ephoto->config->directory);
static void
_ephoto_slideshow_back(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Ephoto *ephoto = data;
Ephoto_Entry *entry = event_info;
switch (ephoto->prev_state)
{
case EPHOTO_STATE_SINGLE:
_ephoto_single_browser_show(ephoto, entry);
break;
case EPHOTO_STATE_THUMB:
_ephoto_thumb_browser_show(ephoto, entry);
break;
default:
ERR("unhandled previous state %d", ephoto->prev_state);
}
elm_win_fullscreen_set(ephoto->win, EINA_FALSE);
}
static void
_ephoto_thumb_browser_view(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Ephoto *ephoto = data;
Ephoto_Entry *entry = event_info;
_ephoto_single_browser_show(ephoto, entry);
}
static void
_ephoto_thumb_browser_changed_directory(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
Ephoto *ephoto = data;
ephoto_single_browser_entry_set(ephoto->single_browser, NULL);
ephoto_slideshow_entry_set(ephoto->slideshow, NULL);
}
static void
_ephoto_thumb_browser_slideshow(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Ephoto *ephoto = data;
Ephoto_Entry *entry = event_info;
_ephoto_slideshow_show(ephoto, entry);
}
static void
_ephoto_single_browser_slideshow(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Ephoto *ephoto = data;
Ephoto_Entry *entry = event_info;
_ephoto_slideshow_show(ephoto, entry);
}
static void
@ -48,13 +122,10 @@ ephoto_window_add(const char *path)
{
Ephoto *ephoto = calloc(1, sizeof(Ephoto));
Ethumb_Client *client = elm_thumb_ethumb_client_get();
Evas_Object *o;
char buf[PATH_MAX];
int w, h;
EINA_SAFETY_ON_NULL_RETURN_VAL(ephoto, NULL);
EPHOTO_EVENT_ENTRY_CREATE_DIR = ecore_event_type_new();
EPHOTO_EVENT_ENTRY_CREATE_THUMB = ecore_event_type_new();
EPHOTO_EVENT_ENTRY_CREATE = ecore_event_type_new();
EPHOTO_EVENT_POPULATE_START = ecore_event_type_new();
EPHOTO_EVENT_POPULATE_END = ecore_event_type_new();
EPHOTO_EVENT_POPULATE_ERROR = ecore_event_type_new();
@ -76,6 +147,7 @@ ephoto_window_add(const char *path)
evas_object_del(ephoto->win);
return NULL;
}
if ((ephoto->config->thumb_gen_size != 128) &&
(ephoto->config->thumb_gen_size != 256) &&
(ephoto->config->thumb_gen_size != 512))
@ -91,72 +163,14 @@ ephoto_window_add(const char *path)
elm_win_resize_object_add(ephoto->win, ephoto->bg);
evas_object_show(ephoto->bg);
ephoto->overlay = elm_bg_add(ephoto->bg);
evas_object_size_hint_weight_set
(ephoto->overlay, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_fill_set(ephoto->overlay, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_bg_color_set(ephoto->overlay, 0, 0, 0);
elm_win_resize_object_add(ephoto->win, ephoto->bg);
evas_object_show(ephoto->bg);
ephoto->layout = elm_layout_add(ephoto->win);
if (!ephoto->layout)
{
evas_object_del(ephoto->win);
return NULL;
}
if (!elm_layout_theme_set
(ephoto->layout, "layout", "application", "content-back"))
{
ERR("Content-back");
evas_object_del(ephoto->win);
return NULL;
}
evas_object_size_hint_weight_set
(ephoto->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_fill_set(ephoto->layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_win_resize_object_add(ephoto->win, ephoto->layout);
ephoto->edje = elm_layout_edje_get(ephoto->layout);
edje_object_signal_callback_add(ephoto->edje, "elm,action,back", "",
_back_clicked, ephoto);
evas_object_show(ephoto->layout);
o = edje_object_part_external_object_get(ephoto->edje, "back");
evas_object_geometry_get(o, 0, 0, &w, &h);
ephoto->pager = elm_pager_add(ephoto->win);
elm_object_style_set(ephoto->pager, "fade_invisible");
evas_object_size_hint_weight_set
(ephoto->pager, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_fill_set
(ephoto->pager, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_win_resize_object_add(ephoto->win, ephoto->pager);
evas_object_show(ephoto->pager);
elm_layout_content_set(ephoto->layout, "elm.swallow.content", ephoto->pager);
ephoto->help_but = elm_button_add(ephoto->win);
o = elm_icon_add(ephoto->help_but);
elm_icon_standard_set(o, "help-browser");
evas_object_size_hint_aspect_set(o, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
elm_button_icon_set(ephoto->help_but, o);
evas_object_size_hint_weight_set
(ephoto->help_but, 0.0, 0.0);
evas_object_size_hint_fill_set
(ephoto->help_but, 0.0, 0.0);
evas_object_size_hint_min_set(ephoto->help_but, w, h);
evas_object_size_hint_max_set(ephoto->help_but, w, h);
evas_object_show(ephoto->help_but);
elm_layout_content_set(ephoto->layout, "elm.swallow.end", ephoto->help_but);
ephoto->list_browser = ephoto_list_browser_add(ephoto, ephoto->pager);
if (!ephoto->list_browser)
{
ERR("could not add list browser");
evas_object_del(ephoto->win);
return NULL;
}
elm_pager_content_push(ephoto->pager, ephoto->list_browser);
ephoto->thumb_browser = ephoto_thumb_browser_add(ephoto, ephoto->pager);
if (!ephoto->thumb_browser)
@ -166,6 +180,14 @@ ephoto_window_add(const char *path)
return NULL;
}
elm_pager_content_push(ephoto->pager, ephoto->thumb_browser);
evas_object_smart_callback_add
(ephoto->thumb_browser, "view", _ephoto_thumb_browser_view, ephoto);
evas_object_smart_callback_add
(ephoto->thumb_browser, "changed,directory",
_ephoto_thumb_browser_changed_directory, ephoto);
evas_object_smart_callback_add
(ephoto->thumb_browser, "slideshow",
_ephoto_thumb_browser_slideshow, ephoto);
ephoto->single_browser = ephoto_single_browser_add(ephoto, ephoto->pager);
if (!ephoto->single_browser)
@ -175,12 +197,26 @@ ephoto_window_add(const char *path)
return NULL;
}
elm_pager_content_push(ephoto->pager, ephoto->single_browser);
evas_object_smart_callback_add
(ephoto->single_browser, "back", _ephoto_single_browser_back, ephoto);
evas_object_smart_callback_add
(ephoto->single_browser, "slideshow",
_ephoto_single_browser_slideshow, ephoto);
ephoto->slideshow = ephoto_slideshow_add(ephoto, ephoto->pager);
if (!ephoto->slideshow)
{
ERR("could not add single browser");
evas_object_del(ephoto->win);
return NULL;
}
elm_pager_content_push(ephoto->pager, ephoto->slideshow);
evas_object_smart_callback_add
(ephoto->slideshow, "back", _ephoto_slideshow_back, ephoto);
if ((!path) || (!ecore_file_exists(path)))
{
char p[PATH_MAX];
snprintf(p, PATH_MAX, "%s/.e/e/fileman/favorites", getenv("HOME"));
path = p;
path = ephoto->config->directory;
if ((path) && (!ecore_file_exists(path))) path = NULL;
if (!path)
{
@ -193,20 +229,22 @@ ephoto_window_add(const char *path)
if (ecore_file_is_dir(path))
{
ephoto_promote_list_browser(ephoto);
ephoto_directory_set(ephoto, path);
_ephoto_thumb_browser_show(ephoto, NULL);
}
else
{
ephoto_single_browser_path_pending_set(ephoto->single_browser, path);
ephoto_promote_single_browser(ephoto, NULL);
char *dir = ecore_file_dir_get(path);
ephoto_directory_set(ephoto, dir);
free(dir);
ephoto_single_browser_path_pending_set(ephoto->single_browser, path);
elm_pager_content_promote(ephoto->pager, ephoto->single_browser);
ephoto->state = EPHOTO_STATE_single;
}
/* TODO restore size from last run as well? */
evas_object_resize(ephoto->win, 800, 600);
evas_object_resize(ephoto->win, 900, 600);
evas_object_show(ephoto->win);
return ephoto->win;
@ -217,56 +255,20 @@ ephoto_title_set(Ephoto *ephoto, const char *title)
{
char buf[1024] = "Ephoto";
if (title) snprintf(buf, sizeof(buf), "Ephoto - %s", title);
if (title) snprintf(buf, sizeof(buf), "%s - Ephoto", title);
elm_win_title_set(ephoto->win, buf);
edje_object_part_text_set(ephoto->edje, "elm.text.title", title);
}
void
ephoto_promote_list_browser(Ephoto *ephoto)
{
elm_pager_content_promote(ephoto->pager, ephoto->list_browser);
edje_object_signal_emit(ephoto->edje, "elm,back,hide", "elm");
_ephoto_state_set(ephoto, EPHOTO_STATE_LIST);
}
void
ephoto_promote_thumb_browser(Ephoto *ephoto)
{
if (elm_bg_overlay_get(ephoto->bg))
{
evas_object_hide(ephoto->overlay);
elm_bg_overlay_unset(ephoto->bg);
}
elm_pager_content_promote(ephoto->pager, ephoto->thumb_browser);
edje_object_signal_emit(ephoto->edje, "elm,back,show", "elm");
_ephoto_state_set(ephoto, EPHOTO_STATE_THUMB);
}
void
ephoto_promote_single_browser(Ephoto *ephoto, Ephoto_Entry *e)
{
elm_pager_content_promote(ephoto->pager, ephoto->single_browser);
elm_bg_overlay_set(ephoto->bg, ephoto->overlay);
if (e)
ephoto_single_browser_entry_set(ephoto->single_browser, e);
_ephoto_state_set(ephoto, EPHOTO_STATE_SINGLE);
}
static int
_entry_cmp(const void *pa, const void *pb)
{
const Ephoto_Entry *a = pa, *b = pb;
int ret, s;
s = strcmp(a->basename, b->basename);
if (s > 0)
ret = 1;
else if (s < 0)
ret = -1;
if (a->is_dir == b->is_dir)
return strcoll(a->basename, b->basename);
else if (a->is_dir)
return -1;
else
ret = 0;
return ret;
return 1;
}
static void
@ -277,19 +279,30 @@ _ephoto_populate_main(void *data, Eio_File *handler __UNUSED__, const Eina_File_
Ephoto_Event_Entry_Create *ev;
e = ephoto_entry_new(ephoto, info->path, info->path + info->name_start);
if (info->type == EINA_FILE_DIR) e->is_dir = EINA_TRUE;
else if (info->type == EINA_FILE_REG) e->is_dir = EINA_FALSE;
else e->is_dir = !_ephoto_eina_file_direct_info_image_useful(info);
if (!ephoto->entries)
ephoto->entries = eina_list_append(ephoto->entries, e);
else
{
int near_cmp;
Eina_List *near_node = eina_list_search_sorted_near_list
(ephoto->entries, _entry_cmp, e, &near_cmp);
if (near_cmp < 0)
ephoto->entries = eina_list_append_relative_list
(ephoto->entries, e, near_node);
else
ephoto->entries = eina_list_prepend_relative_list
(ephoto->entries, e, near_node);
}
ev = calloc(1, sizeof(Ephoto_Event_Entry_Create));
ev->entry = e;
if (ecore_file_is_dir(info->path))
ecore_event_add(EPHOTO_EVENT_ENTRY_CREATE_DIR, ev, NULL, NULL);
else
{
ephoto->entries = eina_list_sorted_insert(ephoto->entries, _entry_cmp, e);
ecore_event_add(EPHOTO_EVENT_ENTRY_CREATE_THUMB, ev, NULL, NULL);
if (ephoto->state == EPHOTO_STATE_LIST)
ephoto_promote_thumb_browser(ephoto);
}
ecore_event_add(EPHOTO_EVENT_ENTRY_CREATE, ev, NULL, NULL);
}
static Eina_Bool
@ -298,10 +311,8 @@ _ephoto_populate_filter(void *data __UNUSED__, Eio_File *handler __UNUSED__, con
const char *bname = info->path + info->name_start;
if (bname[0] == '.') return EINA_FALSE;
if (info->type == EINA_FILE_DIR) return EINA_TRUE;
if (ecore_file_is_dir(info->path))
return EINA_TRUE;
else
return _ephoto_eina_file_direct_info_image_useful(info);
}
@ -356,7 +367,7 @@ ephoto_directory_set(Ephoto *ephoto, const char *path)
{
EINA_SAFETY_ON_NULL_RETURN(ephoto);
ephoto_title_set(ephoto, basename(path));
ephoto_title_set(ephoto, path);
eina_stringshare_replace(&ephoto->config->directory, path);
if (ephoto->job.change_dir) ecore_job_del(ephoto->job.change_dir);
ephoto->job.change_dir = ecore_job_add(_ephoto_change_dir, ephoto);
@ -461,23 +472,6 @@ ephoto_thumb_path_set(Evas_Object *o, const char *path)
elm_thumb_file_set(o, path, NULL);
}
Evas_Object *
ephoto_list_icon_add(Ephoto *ephoto, Evas_Object *parent, const char *standard)
{
Evas_Object *o;
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
o = elm_icon_add(parent);
if (!o) return NULL;
if (standard) elm_icon_standard_set(o, standard);
evas_object_size_hint_aspect_set(o, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
ephoto->dirs = eina_list_append(ephoto->dirs, o);
return o;
}
Ephoto_Entry *
ephoto_entry_new(Ephoto *ephoto, const char *path, const char *label)
{
@ -495,6 +489,7 @@ ephoto_entry_new(Ephoto *ephoto, const char *path, const char *label)
void
ephoto_entry_free(Ephoto_Entry *entry)
{
const char *s;
Ephoto_Entry_Free_Listener *fl;
EINA_LIST_FREE(entry->free_listeners, fl)
@ -505,6 +500,7 @@ ephoto_entry_free(Ephoto_Entry *entry)
EINA_SAFETY_ON_NULL_RETURN(entry);
eina_stringshare_del(entry->path);
eina_stringshare_del(entry->label);
EINA_LIST_FREE(entry->dir_files, s) eina_stringshare_del(s);
free(entry);
}
@ -545,4 +541,3 @@ ephoto_entries_free(Ephoto *ephoto)
Ephoto_Entry *entry;
EINA_LIST_FREE(ephoto->entries, entry) ephoto_entry_free(entry);
}

View File

@ -8,53 +8,52 @@
* elm_photocam and elm_image rotates their images internally.
* Rotating the scroller is not correct and was rejected by Raster and others.
*/
//#define ROTATION
#define ROTATION 0
#define ZOOM_STEP 0.2
typedef struct _Ephoto_Single_Browser Ephoto_Single_Browser;
typedef struct _Ephoto_single_Browser Ephoto_Single_Browser;
typedef struct _Ephoto_Viewer Ephoto_Viewer;
struct _Ephoto_Single_Browser
{
Ephoto *ephoto;
Evas_Object *layout;
Evas_Object *main;
Evas_Object *bar;
Evas_Object *label;
Evas_Object *viewer;
const char *pending_path;
Ephoto_Entry *entry;
Ephoto_Orient orient;
Eina_List *handlers;
Eina_List *entries;
Eina_List *current_index;
};
struct _Ephoto_Viewer
{
Evas_Object *scroller;
Evas_Object *box;
Evas_Object *image;
Evas_Object *photocam;
Evas_Object *scroller;
Evas_Object *image;
double zoom;
Eina_Bool fit:1;
};
static void _zoom_set(Ephoto_Single_Browser *sb, double zoom);
static void _zoom_in(Ephoto_Single_Browser *sb);
static void _zoom_out(Ephoto_Single_Browser *sb);
static Eina_Bool
_path_is_jpeg(const char *path_stringshared)
{
size_t len = eina_stringshare_strlen(path_stringshared);
const char *ext;
if (len < sizeof(".jpg"))
return EINA_FALSE;
if (len < sizeof(".jpg")) return EINA_FALSE;
ext = path_stringshared + len - (sizeof(".jpg") - 1);
if (strcasecmp(ext, ".jpg") == 0)
return EINA_TRUE;
if (strcasecmp(ext, ".jpg") == 0) return EINA_TRUE;
if (len < sizeof(".jpeg"))
return EINA_FALSE;
if (len < sizeof(".jpeg")) return EINA_FALSE;
ext = path_stringshared + len - (sizeof(".jpeg") - 1);
if (strcasecmp(ext, ".jpeg") == 0)
return EINA_TRUE;
if (strcasecmp(ext, ".jpeg") == 0) return EINA_TRUE;
return EINA_FALSE;
}
@ -69,7 +68,6 @@ static void
_viewer_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Viewer *v = data;
free(v);
}
@ -86,8 +84,7 @@ _viewer_add(Evas_Object *parent, const char *path)
obj = v->photocam = elm_photocam_add(parent);
EINA_SAFETY_ON_NULL_GOTO(obj, error);
err = elm_photocam_file_set(obj, path);
if (err != EVAS_LOAD_ERROR_NONE)
goto load_error;
if (err != EVAS_LOAD_ERROR_NONE) goto load_error;
elm_photocam_paused_set(obj, EINA_TRUE);
evas_object_smart_callback_add
(obj, "loaded", _viewer_photocam_loaded, v);
@ -97,25 +94,14 @@ _viewer_add(Evas_Object *parent, const char *path)
Evas_Coord w, h;
obj = v->scroller = elm_scroller_add(parent);
EINA_SAFETY_ON_NULL_GOTO(obj, error);
v->box = elm_box_add(obj);
evas_object_size_hint_weight_set(v->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(v->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(v->box);
v->image = evas_object_image_filled_add(evas_object_evas_get(parent));
evas_object_image_file_set(v->image, path, NULL);
err = evas_object_image_load_error_get(v->image);
if (err != EVAS_LOAD_ERROR_NONE) goto load_error;
evas_object_image_size_get(v->image, &w, &h);
evas_object_size_hint_align_set(v->image, 0.5, 0.5);
evas_object_size_hint_weight_set(v->image, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_min_set(v->image, w, h);
evas_object_size_hint_max_set(v->image, w, h);
evas_object_resize(v->image, w, h);
evas_object_show(v->image);
elm_box_pack_end(v->box, v->image);
elm_scroller_content_set(obj, v->box);
}
evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
@ -135,8 +121,7 @@ static void
_viewer_zoom_apply(Ephoto_Viewer *v, double zoom)
{
v->zoom = zoom;
if (v->photocam)
elm_photocam_zoom_set(v->photocam, 1.0 / zoom);
if (v->photocam) elm_photocam_zoom_set(v->photocam, 1.0 / zoom);
else
{
Evas_Coord w, h;
@ -145,10 +130,6 @@ _viewer_zoom_apply(Ephoto_Viewer *v, double zoom)
h *= zoom;
evas_object_size_hint_min_set(v->image, w, h);
evas_object_size_hint_max_set(v->image, w, h);
elm_box_unpack(v->box, v->image);
elm_scroller_content_unset(v->scroller);
elm_box_pack_end(v->box, v->image);
elm_scroller_content_set(v->scroller, v->box);
}
}
@ -219,9 +200,9 @@ _viewer_zoom_fit(Evas_Object *obj)
Ephoto_Viewer *v = evas_object_data_get(obj, "viewer");
EINA_SAFETY_ON_NULL_RETURN(v);
if (v->fit) return;
v->fit = EINA_TRUE;
if (v->photocam)
evas_object_event_callback_add
(v->photocam, EVAS_CALLBACK_RESIZE, _viewer_resized, v);
@ -232,9 +213,280 @@ _viewer_zoom_fit(Evas_Object *obj)
_viewer_zoom_fit_apply(v);
}
static void
_orient_apply(Ephoto_Single_Browser *sb)
{
#ifdef ROTATION
const char *sig;
switch (sb->orient)
{
case EPHOTO_ORIENT_0:
sig = "state,rotate,0";
break;
case EPHOTO_ORIENT_90:
sig = "state,rotate,90";
break;
case EPHOTO_ORIENT_180:
sig = "state,rotate,180";
break;
case EPHOTO_ORIENT_270:
sig = "state,rotate,270";
break;
case EPHOTO_ORIENT_FLIP_HORIZ:
sig = "state,flip,horiz";
break;
case EPHOTO_ORIENT_FLIP_VERT:
sig = "state,flip,vert";
break;
case EPHOTO_ORIENT_FLIP_HORIZ_90:
sig = "state,flip,horiz,90";
break;
case EPHOTO_ORIENT_FLIP_VERT_90:
sig = "state,flip,vert,90";
break;
default:
return;
}
DBG("orient: %d, signal '%s'", sb->orient, sig);
edje_object_signal_emit(sb->orient_edje, sig, "ephoto");
#else
(void)sb;
#endif
}
#ifdef ROTATION
static void
_rotate_counterclock(Ephoto_Single_Browser *sb)
{
switch (sb->orient)
{
case EPHOTO_ORIENT_0:
sb->orient = EPHOTO_ORIENT_270;
break;
case EPHOTO_ORIENT_90:
sb->orient = EPHOTO_ORIENT_0;
break;
case EPHOTO_ORIENT_180:
sb->orient = EPHOTO_ORIENT_90;
break;
case EPHOTO_ORIENT_270:
sb->orient = EPHOTO_ORIENT_180;
break;
case EPHOTO_ORIENT_FLIP_HORIZ:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90;
break;
case EPHOTO_ORIENT_FLIP_VERT:
sb->orient = EPHOTO_ORIENT_FLIP_VERT_90;
break;
case EPHOTO_ORIENT_FLIP_HORIZ_90:
sb->orient = EPHOTO_ORIENT_FLIP_VERT;
break;
case EPHOTO_ORIENT_FLIP_VERT_90:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ;
break;
}
_orient_apply(sb);
}
static void
_rotate_clock(Ephoto_Single_Browser *sb)
{
switch (sb->orient)
{
case EPHOTO_ORIENT_0:
sb->orient = EPHOTO_ORIENT_90;
break;
case EPHOTO_ORIENT_90:
sb->orient = EPHOTO_ORIENT_180;
break;
case EPHOTO_ORIENT_180:
sb->orient = EPHOTO_ORIENT_270;
break;
case EPHOTO_ORIENT_270:
sb->orient = EPHOTO_ORIENT_0;
break;
case EPHOTO_ORIENT_FLIP_HORIZ:
sb->orient = EPHOTO_ORIENT_FLIP_VERT_90;
break;
case EPHOTO_ORIENT_FLIP_VERT:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90;
break;
case EPHOTO_ORIENT_FLIP_HORIZ_90:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ;
break;
case EPHOTO_ORIENT_FLIP_VERT_90:
sb->orient = EPHOTO_ORIENT_FLIP_VERT;
break;
}
_orient_apply(sb);
}
static void
_flip_horiz(Ephoto_Single_Browser *sb)
{
switch (sb->orient)
{
case EPHOTO_ORIENT_0:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ;
break;
case EPHOTO_ORIENT_90:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90;
break;
case EPHOTO_ORIENT_180:
sb->orient = EPHOTO_ORIENT_FLIP_VERT;
break;
case EPHOTO_ORIENT_270:
sb->orient = EPHOTO_ORIENT_FLIP_VERT_90;
break;
case EPHOTO_ORIENT_FLIP_HORIZ:
sb->orient = EPHOTO_ORIENT_0;
break;
case EPHOTO_ORIENT_FLIP_VERT:
sb->orient = EPHOTO_ORIENT_180;
break;
case EPHOTO_ORIENT_FLIP_HORIZ_90:
sb->orient = EPHOTO_ORIENT_90;
break;
case EPHOTO_ORIENT_FLIP_VERT_90:
sb->orient = EPHOTO_ORIENT_270;
break;
}
_orient_apply(sb);
}
static void
_flip_vert(Ephoto_Single_Browser *sb)
{
switch (sb->orient)
{
case EPHOTO_ORIENT_0:
sb->orient = EPHOTO_ORIENT_FLIP_VERT;
break;
case EPHOTO_ORIENT_90:
sb->orient = EPHOTO_ORIENT_FLIP_VERT_90;
break;
case EPHOTO_ORIENT_180:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ;
break;
case EPHOTO_ORIENT_270:
sb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90;
break;
case EPHOTO_ORIENT_FLIP_HORIZ:
sb->orient = EPHOTO_ORIENT_180;
break;
case EPHOTO_ORIENT_FLIP_VERT:
sb->orient = EPHOTO_ORIENT_0;
break;
case EPHOTO_ORIENT_FLIP_HORIZ_90:
sb->orient = EPHOTO_ORIENT_270;
break;
case EPHOTO_ORIENT_FLIP_VERT_90:
sb->orient = EPHOTO_ORIENT_90;
break;
}
_orient_apply(sb);
}
#endif
static void
_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
{
Ephoto_Single_Browser *sb = data;
Evas_Event_Mouse_Wheel *ev = event_info;
if (!evas_key_modifier_is_set(ev->modifiers, "Control")) return;
if (ev->z > 0) _zoom_in(sb);
else _zoom_out(sb);
}
static Ephoto_Entry *
_first_entry_find(Ephoto_Single_Browser *sb)
{
const Eina_List *l;
Ephoto_Entry *entry;
EINA_SAFETY_ON_NULL_RETURN_VAL(sb->ephoto, NULL);
EINA_LIST_FOREACH(sb->ephoto->entries, l, entry)
if (!entry->is_dir) return entry;
return NULL;
}
static Ephoto_Entry *
_last_entry_find(Ephoto_Single_Browser *sb)
{
const Eina_List *l;
Ephoto_Entry *entry;
EINA_SAFETY_ON_NULL_RETURN_VAL(sb->ephoto, NULL);
EINA_LIST_REVERSE_FOREACH(sb->ephoto->entries, l, entry)
if (!entry->is_dir) return entry;
return NULL;
}
Ephoto_Orient
ephoto_file_orient_get(const char *path)
{
#ifndef HAVE_LIBEXIF
return EPHOTO_ORIENT_0;
#else
Ephoto_Orient orient = EPHOTO_ORIENT_0;
ExifData *exif;
ExifEntry *entry;
ExifByteOrder bo;
if (!_path_is_jpeg(path)) return orient;
exif = exif_data_new_from_file(path);
if (!exif) goto end;
bo = exif_data_get_byte_order(exif);
entry = exif_data_get_entry(exif, EXIF_TAG_ORIENTATION);
if (!entry) goto end_entry;
orient = exif_get_short(entry->data, bo);
DBG("orient=%d", orient);
if ((orient < 1) || (orient > 8))
{
ERR("exif orient not supported: %d", orient);
orient = EPHOTO_ORIENT_0;
}
end_entry:
exif_data_free(exif);
end:
return orient;
#endif
}
static void
_ephoto_single_browser_recalc(Ephoto_Single_Browser *sb)
{
if (sb->viewer)
{
evas_object_del(sb->viewer);
sb->viewer = NULL;
}
if (sb->entry)
{
const char *bname = ecore_file_file_get(sb->entry->path);
sb->viewer = _viewer_add(sb->main, sb->entry->path);
elm_box_pack_end(sb->main, sb->viewer);
evas_object_show(sb->viewer);
evas_object_event_callback_add
(sb->viewer, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel, sb);
elm_label_label_set(sb->label, bname);
ephoto_title_set(sb->ephoto, bname);
sb->orient = ephoto_file_orient_get(sb->entry->path);
_orient_apply(sb);
}
elm_object_focus(sb->main);
}
static void
_zoom_set(Ephoto_Single_Browser *sb, double zoom)
{
DBG("zoom %f", zoom);
if (zoom <= 0.0) return;
_viewer_zoom_set(sb->viewer, zoom);
}
@ -242,8 +494,7 @@ _zoom_set(Ephoto_Single_Browser *sb, double zoom)
static void
_zoom_fit(Ephoto_Single_Browser *sb)
{
if (sb->viewer)
_viewer_zoom_fit(sb->viewer);
if (sb->viewer) _viewer_zoom_fit(sb->viewer);
}
static void
@ -260,6 +511,34 @@ _zoom_out(Ephoto_Single_Browser *sb)
_viewer_zoom_set(sb->viewer, _viewer_zoom_get(sb->viewer) * change);
}
static void
_zoom_in_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_zoom_in(sb);
}
static void
_zoom_out_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_zoom_out(sb);
}
static void
_zoom_1_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_zoom_set(sb, 1.0);
}
static void
_zoom_fit_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_zoom_fit(sb);
}
static int
_entry_cmp(const void *pa, const void *pb)
{
@ -272,20 +551,6 @@ _entry_cmp(const void *pa, const void *pb)
return strcoll(a->path, path);
}
static Ephoto_Entry *
_first_entry_find(Ephoto_Single_Browser *sb)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(sb->ephoto, NULL);
return eina_list_nth(sb->ephoto->entries, 0);
}
static Ephoto_Entry *
_last_entry_find(Ephoto_Single_Browser *sb)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(sb->ephoto, NULL);
return eina_list_data_get(eina_list_last(sb->ephoto->entries));
}
static void
_next_entry(Ephoto_Single_Browser *sb)
{
@ -294,90 +559,135 @@ _next_entry(Ephoto_Single_Browser *sb)
EINA_SAFETY_ON_NULL_RETURN(sb->entry);
node = eina_list_search_sorted_list(sb->ephoto->entries, _entry_cmp, sb->entry->path);
if (!node)
return;
if ((node = node->next))
if (!node) return;
while ((node = node->next))
{
entry = node->data;
if (!entry->is_dir)
break;
}
if (!entry)
entry = _first_entry_find(sb);
if (entry)
ephoto_single_browser_entry_set(sb->layout, entry);
{
DBG("next is '%s'", entry->path);
ephoto_single_browser_entry_set(sb->main, entry);
}
}
static void
_prev_entry(Ephoto_Single_Browser *sb)
{
Ephoto_Entry *entry = NULL;
Eina_List *node;
Ephoto_Entry *entry = NULL;
EINA_SAFETY_ON_NULL_RETURN(sb->entry);
node = eina_list_search_sorted_list(sb->ephoto->entries, _entry_cmp, sb->entry->path);
if (!node)
return;
if ((node = node->prev))
if (!node) return;
while ((node = node->prev))
{
entry = node->data;
if (!entry->is_dir)
break;
}
if (!entry)
entry = _last_entry_find(sb);
if (entry)
ephoto_single_browser_entry_set(sb->layout, entry);
{
DBG("prev is '%s'", entry->path);
ephoto_single_browser_entry_set(sb->main, entry);
}
}
static void
_first_entry(Ephoto_Single_Browser *sb)
{
Ephoto_Entry *entry = _first_entry_find(sb);
if (!entry)
return;
ephoto_single_browser_entry_set(sb->layout, entry);
if (!entry) return;
DBG("first is '%s'", entry->path);
ephoto_single_browser_entry_set(sb->main, entry);
}
static void
_last_entry(Ephoto_Single_Browser *sb)
{
Ephoto_Entry *entry = _last_entry_find(sb);
if (!entry)
return;
ephoto_single_browser_entry_set(sb->layout, entry);
if (!entry) return;
DBG("last is '%s'", entry->path);
ephoto_single_browser_entry_set(sb->main, entry);
}
static void
_viewer_scrolled(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
_go_first(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer");
int sx, sw, cx;
if (!v->fit)
return;
evas_object_geometry_get(sb->viewer, &sx, 0, &sw, 0);
if (v->photocam)
{
Evas_Object *i = elm_photocam_internal_image_get(v->photocam);
evas_object_geometry_get(i, &cx, 0, 0, 0);
_first_entry(sb);
}
else
evas_object_geometry_get(v->image, &cx, 0, 0, 0);
if (cx < (sx-(sw/2)))
_next_entry(sb);
else if (cx > (sw/2))
static void
_go_prev(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_prev_entry(sb);
}
static void
_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
_go_next(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer");
Evas_Event_Mouse_Wheel *ev = event_info;
if (!evas_key_modifier_is_set(ev->modifiers, "Control")) return;
_next_entry(sb);
}
if (ev->z > 0) _zoom_set(sb, v->zoom + ZOOM_STEP);
else _zoom_set(sb, v->zoom - ZOOM_STEP);
static void
_go_last(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_last_entry(sb);
}
#ifdef ROTATION
static void
_go_rotate_counterclock(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_rotate_counterclock(sb);
}
static void
_go_rotate_clock(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_rotate_clock(sb);
}
static void
_go_flip_horiz(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_flip_horiz(sb);
}
static void
_go_flip_vert(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
_flip_vert(sb);
}
#endif
static void
_slideshow(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
if (sb->entry)
evas_object_smart_callback_call(sb->main, "slideshow", sb->entry);
}
static void
_back(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
evas_object_smart_callback_call(sb->main, "back", sb->entry);
}
static void
@ -389,6 +699,7 @@ _key_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event
Eina_Bool shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
const char *k = ev->keyname;
DBG("key pressed '%s'", k);
if (ctrl)
{
if ((!strcmp(k, "plus")) || (!strcmp(k, "equal")))
@ -403,7 +714,10 @@ _key_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event
return;
}
if (!strcmp(k, "Left") || !strcmp(k, "BackSpace"))
if (!strcmp(k, "Escape"))
evas_object_smart_callback_call(sb->main, "back", sb->entry);
else if (!strcmp(k, "Left") || !strcmp(k, "BackSpace"))
_prev_entry(sb);
else if (!strcmp(k, "Right") || !strcmp(k, "space"))
_next_entry(sb);
@ -411,31 +725,23 @@ _key_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event
_first_entry(sb);
else if (!strcmp(k, "End"))
_last_entry(sb);
}
static void
_ephoto_single_browser_recalc(Ephoto_Single_Browser *sb)
#if ROTATION
else if (!strcmp(k, "bracketleft"))
{
if (sb->viewer)
{
evas_object_del(sb->viewer);
sb->viewer = NULL;
if (!shift) _rotate_counterclock(sb);
else _flip_horiz(sb);
}
else if (!strcmp(k, "bracketright"))
{
if (!shift) _rotate_clock(sb);
else _flip_vert(sb);
}
#endif
else if (!strcmp(k, "F5"))
{
if (sb->entry)
{
const char *bname = ecore_file_file_get(sb->entry->path);
sb->viewer = _viewer_add(sb->layout, sb->entry->path);
elm_layout_content_set(sb->layout, "ephoto.swallow.content", sb->viewer);
evas_object_event_callback_add
(sb->viewer, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel, sb);
evas_object_smart_callback_add
(sb->viewer, "scroll", _viewer_scrolled, sb);
evas_object_show(sb->viewer);
ephoto_title_set(sb->ephoto, bname);
evas_object_smart_callback_call(sb->main, "slideshow", sb->entry);
}
elm_object_focus(sb->layout);
}
static void
@ -446,7 +752,7 @@ _entry_free(void *data, const Ephoto_Entry *entry __UNUSED__)
}
static void
_layout_del(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
_main_del(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Single_Browser *sb = data;
Ecore_Event_Handler *handler;
@ -476,6 +782,8 @@ _ephoto_single_entry_create(void *data, int type __UNUSED__, void *event __UNUSE
e = ev->entry;
if (!sb->entry && sb->pending_path && e->path == sb->pending_path)
{
DBG("Adding entry %p for path %s", e, sb->pending_path);
eina_stringshare_del(sb->pending_path);
sb->pending_path = NULL;
ephoto_single_browser_entry_set(sb->ephoto->single_browser, e);
@ -487,26 +795,161 @@ _ephoto_single_entry_create(void *data, int type __UNUSED__, void *event __UNUSE
Evas_Object *
ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent)
{
Evas_Object *box = elm_box_add(parent);
Evas_Object *but, *ic, *sep;
Ephoto_Single_Browser *sb;
EINA_SAFETY_ON_NULL_RETURN_VAL(box, NULL);
sb = calloc(1, sizeof(Ephoto_Single_Browser));
EINA_SAFETY_ON_NULL_GOTO(sb, error);
sb->ephoto = ephoto;
sb->main = box;
elm_box_horizontal_set(sb->main, EINA_FALSE);
elm_box_homogeneous_set(sb->main, EINA_FALSE);
evas_object_event_callback_add(sb->main, EVAS_CALLBACK_DEL, _main_del, sb);
evas_object_event_callback_add
(sb->main, EVAS_CALLBACK_KEY_DOWN, _key_down, sb);
evas_object_data_set(sb->main, "single_browser", sb);
sb->layout = elm_layout_add(parent);
if (!elm_layout_file_set(sb->layout, THEME_FILE, "ephoto/layout/single/browser"))
{
ERR("Could not load style 'ephoto/layout/single/browser' from theme");
goto error;
}
evas_object_size_hint_weight_set
(sb->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_fill_set
(sb->layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_event_callback_add(sb->layout, EVAS_CALLBACK_KEY_DOWN, _key_down, sb);
evas_object_event_callback_add(sb->layout, EVAS_CALLBACK_DEL, _layout_del, sb);
evas_object_data_set(sb->layout, "single_browser", sb);
evas_object_show(sb->layout);
sb->bar = elm_box_add(sb->main);
elm_box_horizontal_set(sb->bar, EINA_TRUE);
elm_box_homogeneous_set(sb->bar, EINA_FALSE);
evas_object_size_hint_weight_set(sb->bar, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(sb->bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(sb->bar);
elm_box_pack_end(sb->main, sb->bar);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/back_grid.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _back, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
sep = elm_separator_add(sb->bar);
elm_box_pack_end(sb->bar, sep);
evas_object_show(sep);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/zoom-in.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _zoom_in_cb, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/zoom-out.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _zoom_out_cb, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/zoom-fit.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _zoom_fit_cb, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/zoom-original.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _zoom_1_cb, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
sep = elm_separator_add(sb->bar);
elm_box_pack_end(sb->bar, sep);
evas_object_show(sep);
sb->label = elm_label_add(sb->bar);
evas_object_size_hint_align_set(sb->label, 0.5, 0.5);
elm_box_pack_end(sb->bar, sb->label);
evas_object_show(sb->label);
sep = elm_separator_add(sb->bar);
elm_box_pack_end(sb->bar, sep);
evas_object_show(sep);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/first.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _go_first, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/back.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _go_prev, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/forward.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _go_next, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/last.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _go_last, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
sep = elm_separator_add(sb->bar);
elm_box_pack_end(sb->bar, sep);
evas_object_show(sep);
but = elm_button_add(sb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/slideshow.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _slideshow, sb);
elm_box_pack_end(sb->bar, but);
evas_object_show(but);
sb->handlers = eina_list_append
(sb->handlers, ecore_event_handler_add
@ -514,12 +957,12 @@ ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent)
sb->handlers = eina_list_append
(sb->handlers, ecore_event_handler_add
(EPHOTO_EVENT_ENTRY_CREATE_THUMB, _ephoto_single_entry_create, sb));
(EPHOTO_EVENT_ENTRY_CREATE, _ephoto_single_entry_create, sb));
return sb->layout;
return sb->main;
error:
evas_object_del(sb->layout);
evas_object_del(sb->main);
return NULL;
}
@ -527,27 +970,20 @@ void
ephoto_single_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry)
{
Ephoto_Single_Browser *sb = evas_object_data_get(obj, "single_browser");
Eina_Bool same_file = EINA_FALSE;
EINA_SAFETY_ON_NULL_RETURN(sb);
DBG("entry %p, was %p", entry, sb->entry);
if (sb->entry)
{
ephoto_entry_free_listener_del(sb->entry, _entry_free, sb);
if (entry && entry->path == sb->entry->path)
same_file = EINA_TRUE;
}
sb->entry = entry;
if (entry)
ephoto_entry_free_listener_add(entry, _entry_free, sb);
if (sb->entry || !same_file)
{
_ephoto_single_browser_recalc(sb);
_zoom_fit(sb);
}
}
void
ephoto_single_browser_path_pending_set(Evas_Object *obj, const char *path)
@ -558,4 +994,3 @@ ephoto_single_browser_path_pending_set(Evas_Object *obj, const char *path)
DBG("Setting pending path '%s'", path);
sb->pending_path = eina_stringshare_add(path);
}

193
src/bin/ephoto_slideshow.c Normal file
View File

@ -0,0 +1,193 @@
#include "ephoto.h"
typedef struct _Ephoto_Slideshow Ephoto_Slideshow;
struct _Ephoto_Slideshow
{
Ephoto *ephoto;
Evas_Object *slideshow;
Ephoto_Entry *entry;
};
static void
_key_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
{
Ephoto_Slideshow *ss = data;
Evas_Event_Key_Down *ev = event_info;
const char *k = ev->keyname;
if (!strcmp(k, "Escape"))
{
Evas_Object *win = ss->ephoto->win;
Elm_Slideshow_Item *item;
Ephoto_Entry *entry;
if (elm_win_fullscreen_get(win))
elm_win_fullscreen_set(win, EINA_FALSE);
item = elm_slideshow_item_current_get(ss->slideshow);
if (item) entry = elm_slideshow_item_data_get(item);
else entry = ss->entry;
evas_object_smart_callback_call(ss->slideshow, "back", entry);
}
else if (!strcmp(k, "F11"))
{
Evas_Object *win = ss->ephoto->win;
elm_win_fullscreen_set(win, !elm_win_fullscreen_get(win));
}
}
static void
_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Slideshow *ss = data;
evas_object_smart_callback_call(ss->slideshow, "back", ss->entry);
}
static void
_entry_free(void *data, const Ephoto_Entry *entry __UNUSED__)
{
Ephoto_Slideshow *ss = data;
ss->entry = NULL;
}
static void
_slideshow_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Slideshow *ss = data;
if (ss->entry)
ephoto_entry_free_listener_del(ss->entry, _entry_free, ss);
free(ss);
}
Evas_Object *
ephoto_slideshow_add(Ephoto *ephoto, Evas_Object *parent)
{
Evas_Object *slideshow = elm_slideshow_add(parent);
Ephoto_Slideshow *ss;
EINA_SAFETY_ON_NULL_RETURN_VAL(slideshow, NULL);
ss = calloc(1, sizeof(Ephoto_Slideshow));
EINA_SAFETY_ON_NULL_GOTO(ss, error);
ss->ephoto = ephoto;
ss->slideshow = slideshow;
evas_object_event_callback_add
(slideshow, EVAS_CALLBACK_DEL, _slideshow_del, ss);
evas_object_event_callback_add
(slideshow, EVAS_CALLBACK_KEY_DOWN, _key_down, ss);
evas_object_event_callback_add
(slideshow, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, ss);
evas_object_data_set(slideshow, "slideshow", ss);
elm_slideshow_loop_set(slideshow, EINA_TRUE);
elm_slideshow_layout_set(slideshow, "fullscreen");
evas_object_size_hint_weight_set
(slideshow, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(slideshow, EVAS_HINT_FILL, EVAS_HINT_FILL);
return ss->slideshow;
error:
evas_object_del(slideshow);
return NULL;
}
static void
_image_resized(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *image, void *event_info __UNUSED__)
{
Evas_Map *map = evas_map_new(4);
Evas_Coord cx, cy, x, y, w, h;
int orient = (long)evas_object_data_get(image, "orient");
evas_object_geometry_get(image, &x, &y, &w, &h);
evas_map_util_points_populate_from_geometry(map, x, y, w, h, 0);
cx = x + w / 2;
cy = y + h / 2;
switch (orient)
{
case EPHOTO_ORIENT_0:
break;
case EPHOTO_ORIENT_90:
evas_map_util_rotate(map, 90.0, cx, cy);
evas_object_map_enable_set(image, EINA_TRUE);
evas_object_map_set(image, map);
printf("rotated 90 around %d,%d (%dx%d)\n", cx, cy, w, h);
break;
case EPHOTO_ORIENT_180:
evas_map_util_rotate(map, 180.0, cx, cy);
evas_object_map_enable_set(image, EINA_TRUE);
evas_object_map_set(image, map);
printf("rotated 180 around %d,%d (%d,%d %dx%d)\n", cx, cy, x, y, w, h);
break;
case EPHOTO_ORIENT_270:
evas_map_util_rotate(map, 270.0, cx, cy);
evas_object_map_enable_set(image, EINA_TRUE);
evas_object_map_set(image, map);
printf("rotated 270 around %d,%d (%dx%d)\n", cx, cy, w, h);
break;
default:
ERR("unknown orient %d", orient);
}
evas_map_free(map);
}
static Evas_Object *
_slideshow_item_get(void *data, Evas_Object *obj)
{
Ephoto_Entry *entry = data;
/* TODO use viewer from ephoto_single_browser.c */
/* TODO consider using exif rotation, see ephoto_single_browser.c */
Evas_Object *image = elm_photo_add(obj);
elm_photo_file_set(image, entry->path);
elm_photo_fill_inside_set(image, EINA_TRUE);
elm_object_style_set(image, "shadow");
evas_object_data_set
(image, "orient", (void*)(long)ephoto_file_orient_get(entry->path));
evas_object_event_callback_add
(image, EVAS_CALLBACK_RESIZE, _image_resized, NULL);
return image;
}
static const Elm_Slideshow_Item_Class _item_cls = {{_slideshow_item_get, NULL}};
void
ephoto_slideshow_entry_set(Evas_Object *obj, Ephoto_Entry *entry)
{
Ephoto_Slideshow *ss = evas_object_data_get(obj, "slideshow");
Ephoto_Config *conf;
Ephoto_Entry *itr;
const Eina_List *l;
EINA_SAFETY_ON_NULL_RETURN(ss);
conf = ss->ephoto->config;
DBG("entry %p, was %p", entry, ss->entry);
if (ss->entry)
ephoto_entry_free_listener_del(ss->entry, _entry_free, ss);
ss->entry = entry;
if (entry)
ephoto_entry_free_listener_add(entry, _entry_free, ss);
elm_slideshow_loop_set(ss->slideshow, EINA_TRUE); /* move to config? */
elm_slideshow_transition_set(ss->slideshow, conf->slideshow_transition);
elm_slideshow_timeout_set(ss->slideshow, conf->slideshow_timeout);
elm_slideshow_clear(ss->slideshow);
if (!entry) return;
elm_win_fullscreen_set(ss->ephoto->win, EINA_TRUE);
EINA_LIST_FOREACH(ss->ephoto->entries, l, itr)
{
Elm_Slideshow_Item *item;
if (itr->is_dir) continue;
item = elm_slideshow_item_add(ss->slideshow, &_item_cls, itr);
if (itr == entry) elm_slideshow_show(item);
}
}

View File

@ -6,21 +6,31 @@
#define TODO_ITEM_MIN_BATCH 16
#define PARENT_DIR "Up"
typedef struct _Ephoto_Thumb_Browser Ephoto_Thumb_Browser;
struct _Ephoto_Thumb_Browser
{
Ephoto *ephoto;
Ephoto_Entry *entry;
Evas_Object *main;
Evas_Object *bar;
Evas_Object *fsel;
Evas_Object *grid;
Eio_File *ls;
Eina_List *todo_items;
Eina_List *grid_items;
Eina_List *handlers;
struct {
Elm_Toolbar_Item *zoom_in;
Elm_Toolbar_Item *zoom_out;
Elm_Toolbar_Item *view_single;
Elm_Toolbar_Item *slideshow;
} action;
struct {
Ecore_Animator *todo_items;
} animator;
Eina_Bool layout_deleted : 1;
Eina_Bool main_deleted : 1;
};
static void
@ -37,6 +47,16 @@ _grid_items_free(Ephoto_Thumb_Browser *tb)
tb->grid_items = NULL;
}
static Ephoto_Entry *
_first_file_entry_find(Ephoto_Thumb_Browser *tb)
{
const Eina_List *l;
Ephoto_Entry *entry;
EINA_LIST_FOREACH(tb->ephoto->entries, l, entry)
if (!entry->is_dir) return entry;
return NULL;
}
static char *
_ephoto_thumb_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
{
@ -44,6 +64,54 @@ _ephoto_thumb_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char
return strdup(e->label);
}
static Evas_Object *
_ephoto_thumb_dir_icon_get(void *data, Evas_Object *obj, const char *part)
{
Ephoto_Entry *e = data;
const char *f;
int n;
if (strncmp(part, "elm.swallow.icon.", sizeof("elm.swallow.icon.") - 1) != 0)
return NULL;
n = atoi(part + sizeof("elm.swallow.icon.") - 1);
if (n < 1)
return NULL;
n--;
f = eina_list_nth(e->dir_files, n);
if (f)
{
Evas_Object *o;
o = ephoto_thumb_add(e->ephoto, obj, f);
//elm_object_style_set(o, "default");
return o;
}
if (e->dir_files_checked)
return NULL;
return ephoto_directory_thumb_add(obj, e);
}
static Eina_Bool
_ephoto_thumb_dir_state_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
{
Ephoto_Entry *e = data;
int n;
if (strcmp(part, "have_files") == 0)
return !!e->dir_files;
if (strncmp(part, "have_file.", sizeof("have_file.") - 1) != 0)
return EINA_FALSE;
n = atoi(part + sizeof("have_file.") - 1);
if (n < 1)
return EINA_FALSE;
return n <= (int)eina_list_count(e->dir_files);
}
static Evas_Object *
_ephoto_thumb_file_icon_get(void *data, Evas_Object *obj, const char *part __UNUSED__)
{
@ -62,6 +130,26 @@ _ephoto_thumb_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
*/
}
static const Elm_Gengrid_Item_Class _ephoto_thumb_up_class = {
"ephoto-up",
{
_ephoto_thumb_item_label_get,
NULL,
NULL,
_ephoto_thumb_item_del
}
};
static const Elm_Gengrid_Item_Class _ephoto_thumb_dir_class = {
"ephoto-album-preview",
{
_ephoto_thumb_item_label_get,
_ephoto_thumb_dir_icon_get,
_ephoto_thumb_dir_state_get,
_ephoto_thumb_item_del
}
};
static const Elm_Gengrid_Item_Class _ephoto_thumb_file_class = {
"thumb",
{
@ -75,56 +163,59 @@ static const Elm_Gengrid_Item_Class _ephoto_thumb_file_class = {
static int
_entry_cmp(const void *pa, const void *pb)
{
const Ephoto_Entry *a = pa, *b = pb;
int ret, s;
const Elm_Gengrid_Item *ia = pa;
const Ephoto_Entry *a, *b = pb;
s = strcmp(a->basename, b->basename);
if (s > 0)
ret = 1;
else if (s < 0)
ret = -1;
a = elm_gengrid_item_data_get(ia);
if (a->is_dir == b->is_dir)
return strcoll(a->basename, b->basename);
else if (a->is_dir)
return -1;
else
ret = 0;
return ret;
return 1;
}
static void
_entry_item_add(Ephoto_Thumb_Browser *tb, Ephoto_Entry *e)
{
const Elm_Gengrid_Item_Class *ic;
int near_cmp;
Elm_Gengrid_Item *near_item = NULL;
Eina_List *near_node = NULL;
ic = &_ephoto_thumb_file_class;
near_node = eina_list_search_sorted_near_list
(tb->grid_items, _entry_cmp, e, &near_cmp);
if (!tb->grid_items)
if (near_node)
near_item = near_node->data;
if (e->is_dir) ic = &_ephoto_thumb_dir_class;
else ic = &_ephoto_thumb_file_class;
if (!near_item)
{
e->item = elm_gengrid_item_append(tb->grid, ic, e, NULL, NULL);
tb->grid_items = eina_list_append(tb->grid_items, e);
tb->grid_items = eina_list_append(tb->grid_items, e->item);
}
else
{
int near_cmp;
Ephoto_Entry *near_entry;
Elm_Gengrid_Item *near_item;
Eina_List *near_node = eina_list_search_sorted_near_list
(tb->grid_items, _entry_cmp, e, &near_cmp);
near_entry = near_node->data;
near_item = near_entry->item;
if (near_cmp < 0)
{
e->item = elm_gengrid_item_insert_after
(tb->grid, ic, e, near_item, NULL, NULL);
tb->grid_items = eina_list_append_relative_list
(tb->grid_items, e, near_node);
tb->grid_items = eina_list_append_relative
(tb->grid_items, e->item, near_item);
}
else
{
e->item = elm_gengrid_item_insert_before
(tb->grid, ic, e, near_item, NULL, NULL);
tb->grid_items = eina_list_prepend_relative_list
(tb->grid_items, e, near_node);
tb->grid_items = eina_list_prepend_relative
(tb->grid_items, e->item, near_item);
}
}
if (e->item)
elm_gengrid_item_data_set(e->item, e);
else
@ -135,6 +226,27 @@ _entry_item_add(Ephoto_Thumb_Browser *tb, Ephoto_Entry *e)
}
}
static void
_up_item_add_if_required(Ephoto_Thumb_Browser *tb)
{
Ephoto_Entry *entry;
char *parent_dir;
if ((strcmp(tb->ephoto->config->directory, "/") == 0))
return;
parent_dir = ecore_file_dir_get(tb->ephoto->config->directory);
if (!parent_dir) return;
entry = ephoto_entry_new(tb->ephoto, parent_dir, PARENT_DIR);
free(parent_dir);
EINA_SAFETY_ON_NULL_RETURN(entry);
entry->is_up = EINA_TRUE;
entry->is_dir = EINA_TRUE;
entry->item = elm_gengrid_item_append
(tb->grid, &_ephoto_thumb_up_class, entry, NULL, NULL);
}
static Eina_Bool
_todo_items_process(void *data)
{
@ -144,6 +256,8 @@ _todo_items_process(void *data)
if ((tb->ls) && (eina_list_count(tb->todo_items) < TODO_ITEM_MIN_BATCH))
return EINA_TRUE;
_up_item_add_if_required(tb);
tb->animator.todo_items = NULL;
EINA_LIST_FREE(tb->todo_items, entry)
@ -161,7 +275,28 @@ _ephoto_thumb_selected(void *data, Evas_Object *o __UNUSED__, void *event_info)
elm_gengrid_item_selected_set(it, EINA_FALSE);
ephoto_promote_single_browser(tb->ephoto, e);
if (e->is_dir)
ephoto_directory_set(tb->ephoto, e->path);
else
evas_object_smart_callback_call(tb->main, "view", e);
}
static void
_changed_dir(void *data, Evas_Object *o __UNUSED__, void *event_info)
{
Ephoto_Thumb_Browser *tb = data;
const char *path = event_info;
if (!path) return;
ephoto_directory_set(tb->ephoto, path);
}
static void
_changed_dir_text(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Thumb_Browser *tb = data;
const char *path = elm_fileselector_entry_path_get(tb->fsel);
if (ecore_file_is_dir(path))
ephoto_directory_set(tb->ephoto, path);
}
static void
@ -175,7 +310,98 @@ _zoom_set(Ephoto_Thumb_Browser *tb, int zoom)
}
static void
_grid_del(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
_zoom_in(void *data, Evas_Object *o, void *event_info __UNUSED__)
{
Ephoto_Thumb_Browser *tb = data;
Evas_Object *min = evas_object_data_get(o, "min");
int zoom = tb->ephoto->config->thumb_size + ZOOM_STEP;
_zoom_set(tb, zoom);
if (zoom >= ZOOM_MAX) elm_object_disabled_set(o, EINA_TRUE);
if (zoom > ZOOM_MIN) elm_object_disabled_set(min, EINA_FALSE);
}
static void
_zoom_out(void *data, Evas_Object *o, void *event_info __UNUSED__)
{
Ephoto_Thumb_Browser *tb = data;
Evas_Object *max = evas_object_data_get(o, "max");
int zoom = tb->ephoto->config->thumb_size - ZOOM_STEP;
_zoom_set(tb, zoom);
if (zoom <= ZOOM_MIN) elm_object_disabled_set(o, EINA_TRUE);
if (zoom < ZOOM_MAX) elm_object_disabled_set(max, EINA_FALSE);
}
static void
_view_single(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Thumb_Browser *tb = data;
Elm_Gengrid_Item *it = elm_gengrid_selected_item_get(tb->grid);
Ephoto_Entry *entry;
if (it) entry = elm_gengrid_item_data_get(it);
else entry = _first_file_entry_find(tb);
if (!entry) return;
if (entry->is_dir)
ephoto_directory_set(tb->ephoto, entry->path);
else
evas_object_smart_callback_call(tb->main, "view", entry);
}
static void
_slideshow(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Thumb_Browser *tb = data;
Elm_Gengrid_Item *it = elm_gengrid_selected_item_get(tb->grid);
Ephoto_Entry *entry;
if (it) entry = elm_gengrid_item_data_get(it);
else entry = _first_file_entry_find(tb);
if (!entry) return;
evas_object_smart_callback_call(tb->main, "slideshow", entry);
}
static void
_key_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
{
Ephoto_Thumb_Browser *tb = data;
Evas_Event_Key_Down *ev = event_info;
Eina_Bool alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
const char *k = ev->keyname;
if (alt)
{
if (!strcmp(k, "Up"))
{
if (strcmp(tb->ephoto->config->directory, "/") != 0)
{
char *parent = ecore_file_dir_get
(tb->ephoto->config->directory);
if (parent)
ephoto_directory_set(tb->ephoto, parent);
free(parent);
}
}
return;
}
if (!strcmp(k, "F5"))
{
Elm_Gengrid_Item *it = elm_gengrid_selected_item_get(tb->grid);
Ephoto_Entry *entry;
if (it) entry = elm_gengrid_item_data_get(it);
else entry = _first_file_entry_find(tb);
if (entry)
evas_object_smart_callback_call(tb->main, "slideshow", entry);
}
}
static void
_main_del(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
{
Ephoto_Thumb_Browser *tb = data;
Ecore_Event_Handler *handler;
@ -192,7 +418,7 @@ _grid_del(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event
}
if (tb->ls)
{
tb->layout_deleted = EINA_TRUE;
tb->main_deleted = EINA_TRUE;
eio_file_cancel(tb->ls);
return;
}
@ -204,9 +430,12 @@ _ephoto_thumb_populate_start(void *data, int type __UNUSED__, void *event __UNUS
{
Ephoto_Thumb_Browser *tb = data;
evas_object_smart_callback_call(tb->main, "changed,directory", NULL);
_todo_items_free(tb);
_grid_items_free(tb);
elm_gengrid_clear(tb->grid);
elm_fileselector_entry_path_set(tb->fsel, tb->ephoto->config->directory);
return ECORE_CALLBACK_PASS_ON;
}
@ -217,12 +446,14 @@ _ephoto_thumb_populate_end(void *data, int type __UNUSED__, void *event __UNUSED
Ephoto_Thumb_Browser *tb = data;
tb->ls = NULL;
if (tb->layout_deleted)
if (tb->main_deleted)
{
free(tb);
return ECORE_CALLBACK_PASS_ON;
}
if (!tb->animator.todo_items) _up_item_add_if_required(tb);
return ECORE_CALLBACK_PASS_ON;
}
@ -251,26 +482,116 @@ _ephoto_thumb_entry_create(void *data, int type __UNUSED__, void *event)
Evas_Object *
ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent)
{
Evas_Object *box = elm_box_add(parent);
Evas_Object *ic, *but, *min, *max;
Ephoto_Thumb_Browser *tb;
EINA_SAFETY_ON_NULL_RETURN_VAL(box, NULL);
tb = calloc(1, sizeof(Ephoto_Thumb_Browser));
EINA_SAFETY_ON_NULL_GOTO(tb, error);
tb->ephoto = ephoto;
tb->grid = elm_gengrid_add(parent);
elm_theme_extension_add(NULL, PACKAGE_DATA_DIR "/themes/default/ephoto.edj");
tb->ephoto = ephoto;
tb->main = box;
elm_box_horizontal_set(tb->main, EINA_FALSE);
elm_box_homogeneous_set(tb->main, EINA_FALSE);
evas_object_event_callback_add(tb->main, EVAS_CALLBACK_DEL, _main_del, tb);
evas_object_event_callback_add
(tb->main, EVAS_CALLBACK_KEY_DOWN, _key_down, tb);
evas_object_data_set(tb->main, "thumb_browser", tb);
tb->bar = elm_box_add(tb->main);
elm_box_horizontal_set(tb->bar, EINA_TRUE);
elm_box_homogeneous_set(tb->bar, EINA_FALSE);
evas_object_size_hint_weight_set(tb->bar, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(tb->bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(tb->bar);
elm_box_pack_end(tb->main, tb->bar);
but = elm_button_add(tb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/single.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _view_single, tb);
elm_box_pack_end(tb->bar, but);
evas_object_show(but);
but = elm_button_add(tb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/slideshow.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _slideshow, tb);
elm_box_pack_end(tb->bar, but);
evas_object_show(but);
tb->fsel = elm_fileselector_entry_add(tb->bar);
EINA_SAFETY_ON_NULL_GOTO(tb->fsel, error);
evas_object_size_hint_weight_set(tb->fsel, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(tb->fsel, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_fileselector_entry_button_label_set(tb->fsel, "Choose...");
elm_fileselector_entry_folder_only_set(tb->fsel, EINA_TRUE);
evas_object_smart_callback_add
(tb->fsel, "file,chosen", _changed_dir, tb);
evas_object_smart_callback_add
(tb->fsel, "activated", _changed_dir_text, tb);
evas_object_show(tb->fsel);
elm_box_pack_end(tb->bar, tb->fsel);
but = elm_button_add(tb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/zoom-in.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _zoom_in, tb);
elm_box_pack_end(tb->bar, but);
evas_object_show(but);
max = but;
but = elm_button_add(tb->bar);
ic = elm_icon_add(but);
elm_icon_file_set(ic, PACKAGE_DATA_DIR "/images/zoom-out.png", NULL);
elm_button_icon_set(but, ic);
evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(but, "clicked", _zoom_out, tb);
elm_box_pack_end(tb->bar, but);
evas_object_show(but);
min = but;
evas_object_data_set(max, "min", min);
evas_object_data_set(min, "max", max);
tb->grid = elm_gengrid_add(tb->main);
EINA_SAFETY_ON_NULL_GOTO(tb->grid, error);
evas_object_size_hint_weight_set
(tb->grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(tb->grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_gengrid_align_set(tb->grid, 0.5, 0.5);
elm_gengrid_bounce_set(tb->grid, EINA_FALSE, EINA_TRUE);
evas_object_size_hint_align_set
(tb->grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_size_hint_weight_set
(tb->grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_smart_callback_add
(tb->grid, "selected", _ephoto_thumb_selected, tb);
_zoom_set(tb, tb->ephoto->config->thumb_size);
evas_object_event_callback_add(tb->grid, EVAS_CALLBACK_DEL, _grid_del, tb);
evas_object_data_set(tb->grid, "thumb_browser", tb);
evas_object_show(tb->grid);
elm_box_pack_end(tb->main, tb->grid);
tb->handlers = eina_list_append
(tb->handlers, ecore_event_handler_add
@ -286,18 +607,11 @@ ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent)
tb->handlers = eina_list_append
(tb->handlers, ecore_event_handler_add
(EPHOTO_EVENT_ENTRY_CREATE_THUMB, _ephoto_thumb_entry_create, tb));
(EPHOTO_EVENT_ENTRY_CREATE, _ephoto_thumb_entry_create, tb));
return tb->grid;
return tb->main;
error:
evas_object_del(tb->grid);
evas_object_del(tb->main);
return NULL;
}
void
ephoto_thumb_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry)
{
Ephoto_Thumb_Browser *tb = evas_object_data_get(obj, "thumb_browser");
tb->entry = entry;
}