diff --git a/data/themes/default/ephoto.edc b/data/themes/default/ephoto.edc index 370e0fe..00f7152 100644 --- a/data/themes/default/ephoto.edc +++ b/data/themes/default/ephoto.edc @@ -1,313 +1,289 @@ -externals { - external: "elm"; -} - collections { - images { - image: "up-128.png" COMP; - image: "directory-128.png" COMP; - image: "raise.png" COMP; - } - 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; - inherit: "default" 0.0; - map { - on: 1; - rotation.z: 0; - } - } - description { state: "rotate_90" 0.0; - inherit: "default" 0.0; - map { - on: 1; - rotation.z: 90; - } - } - description { state: "rotate_180" 0.0; - inherit: "default" 0.0; - map { - on: 1; - rotation.z: 180; - } - } - description { state: "rotate_270" 0.0; - inherit: "default" 0.0; - map { - on: 1; - rotation.z: 270; - } - } - description { state: "flip_horiz" 0.0; - inherit: "default" 0.0; - map { - on: 1; - rotation.y: 180; - } - } - description { state: "flip_vert" 0.0; - inherit: "default" 0.0; - map { - on: 1; - rotation.x: 180; - } - } - description { state: "flip_horiz_90" 0.0; - inherit: "default" 0.0; - map { - on: 1; - rotation { - z: 90; - y: 180; - } - } - } - description { state: "flip_vert_90" 0.0; - inherit: "default" 0.0; - map { - on: 1; - rotation { - z: 90; - x: 180; - } - } - } - } - programs { - program { - signal: "state,rotate,0"; - source: "ephoto"; - action: STATE_SET "rotate_0" 0.0; - target: "elm.swallow.content"; - } - program { - signal: "state,rotate,90"; - source: "ephoto"; - action: STATE_SET "rotate_90" 0.0; - target: "elm.swallow.content"; - } - program { - signal: "state,rotate,180"; - source: "ephoto"; - action: STATE_SET "rotate_180" 0.0; - target: "elm.swallow.content"; - } - program { - signal: "state,rotate,270"; - source: "ephoto"; - action: STATE_SET "rotate_270" 0.0; - target: "elm.swallow.content"; - } - program { - signal: "state,flip,horiz"; - source: "ephoto"; - action: STATE_SET "flip_horiz" 0.0; - target: "elm.swallow.content"; - } - program { - signal: "state,flip,vert"; - source: "ephoto"; - action: STATE_SET "flip_vert" 0.0; - target: "elm.swallow.content"; - } - program { - signal: "state,flip,horiz,90"; - source: "ephoto"; - action: STATE_SET "flip_horiz_90" 0.0; - target: "elm.swallow.content"; - } - program { - signal: "state,flip,vert,90"; - source: "ephoto"; - action: STATE_SET "flip_vert_90" 0.0; - target: "elm.swallow.content"; - } - } - } - } - group { name: "ephoto,thumb,grid"; - parts { - part { name: "ephoto.swallow.content.thumb"; - 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; - } - } - part { name: "overlay"; - type: RECT; - mouse_events: 1; - description { - min: 1 40; - max: 9999 40; - fixed: 0 1; - state: "default" 0.0; - rel1.to: "ephoto.swallow.content.thumb"; - rel1.relative: 0.0 0.0; - rel1.offset: 5 45; - rel2.to: "ephoto.swallow.content.thumb"; - rel2.relative: 1.0 0.0; - rel2.offset: -5 0; - color: 0 0 0 120; - } - description { - state: "lowered" 0.0; - rel1.to: "ephoto.swallow.content.thumb"; - rel1.relative: 0.0 0.0; - rel1.offset: 5 5; - rel2.to: "ephoto.swallow.content.thumb"; - rel2.relative: 1.0 1.0; - rel2.offset: -5 -5; - color: 255 255 255 255; - } - } - part { name: "ephoto.swallow.content.dir"; - type: SWALLOW; - mouse_events: 1; - description { - state: "default" 0.0; - visible: 0; - rel1.to: "ephoto.swallow.content.thumb"; - rel1.relative: 0.0 0.0; - rel1.offset: 0 0; - rel1.to: "ephoto.swallow.content.thumb"; - rel2.relative: 1.0 1.0; - rel2.offset: -1 -1; - } - description { - state: "lowered" 0.0; - inherit: "default" 0.0; - visible: 1; - } - } - part { name: "up"; - type: IMAGE; - mouse_events: 1; - description - { - min: 32 32; - max: 32 32; - fixed: 1 1; - state: "default" 0.0; - rel1.to: "overlay"; - rel1.relative: 0.0 0.0; - rel1.offset: 20 20; - rel2.to: "overlay"; - rel2.relative: 0.0 0.0; - rel2.offset: 20 20; - image.normal: "up-128.png"; - } - description { - state: "lowered" 0.0; - inherit: "default" 0.0; - visible: 0; - } - } - part { name: "directory"; - type: IMAGE; - mouse_events: 1; - description - { - min: 32 32; - max: 32 32; - fixed: 1 1; - state: "default" 0.0; - visible: 1; - rel1.to: "overlay"; - rel1.relative: 1.0 0.0; - rel1.offset: -20 20; - rel2.to: "overlay"; - rel2.relative: 1.0 0.0; - rel2.offset: -20 20; - image.normal: "directory-128.png"; - } - description - { - state: "lowered" 0.0; - inherit: "default" 0.0; - visible: 0; - } - } - part { name: "raise"; - type: IMAGE; - mouse_events: 1; - description - { - min: 32 32; - max: 32 32; - fixed: 1 1; - visible: 0; - state: "default" 0.0; - rel1.to: "overlay"; - rel1.relative: 1.0 0.0; - rel1.offset: -20 20; - rel2.to: "overlay"; - rel2.relative: 1.0 0.0; - rel2.offset: -20 20; - image.normal: "raise.png"; - } - description - { - state: "lowered" 0.0; - inherit: "default" 0.0; - visible: 1; - } - } - } - programs { - program { name: "up_clicked"; - source: "up"; - signal: "mouse,up,*"; - action: SIGNAL_EMIT "ephoto.signal.up" "ephoto"; - } - program { name: "dir_clicked"; - source: "directory"; - signal: "mouse,up,*"; - action: SIGNAL_EMIT "ephoto.signal.dir" "ephoto"; - after: "lower2"; - } - program { name: "raise_clicked"; - source: "raise"; - signal: "mouse,up,*"; - action: SIGNAL_EMIT "ephoto.signal.raise" "ephoto"; - after: "raise2"; - } - program { name: "lower"; - action: STATE_SET "lowered" 0.0; - transition: ACCELERATE 0.6; - target: "overlay"; - after: "lower3"; - } - program { name: "lower2"; - action: STATE_SET "lowered" 0.0; - target: "directory"; - target: "raise"; - after: "lower"; - } - program { name: "lower3"; - action: STATE_SET "lowered" 0.0; - target: "ephoto.swallow.content.dir"; - } - program { name: "raise"; - action: STATE_SET "default" 0.0; - transition: ACCELERATE 0.6; - target: "overlay"; - } - program { name: "raise2"; - action: STATE_SET "default" 0.0; - target: "directory"; - target: "raise"; - target: "ephoto.swallow.content.dir"; - after: "raise"; - } - } - } + group + { + name: "flow"; + parts + { + part + { + name: "flow"; + type: RECT; + 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; + color: 0 0 0 255; + } + } + part + { + name: "offscreen_left"; + type: SWALLOW; + mouse_events: 1; + description + { + state: default 0.0; + visible: 0; + rel1.relative: 0.0 0.4; + rel1.offset: 0 0; + rel2.relative: 0.0 0.6; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: right 0.0; + visible: 1; + rel1.relative: 0.0 0.3; + rel1.offset: 0 0; + rel2.relative: 0.1 0.7; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: left 0.0; + visible: 0; + rel1.relative: 1.0 0.4; + rel1.offset: 0 0; + rel2.relative: 1.0 0.6; + rel2.offset: 0 0; + color: 255 255 255 255; + } + } + part + { + name: "left"; + type: SWALLOW; + mouse_events: 1; + description + { + state: default 0.0; + visible: 1; + rel1.relative: 0.0 0.3; + rel1.offset: 0 0; + rel2.relative: 0.1 0.7; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: right 0.0; + rel1.relative: 0.2 0.2; + rel1.offset: 0 0; + rel2.relative: 0.8 0.8; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: left 0.0; + rel1.relative: 0.0 0.4; + rel1.offset: 0 0; + rel2.relative: 0.0 0.6; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: full 0.0; + inherit: default 0.0; + visible: 0; + color: 255 255 255 0; + } + } + part + { + name: "right"; + type: SWALLOW; + mouse_events: 1; + description + { + state: default 0.0; + visible: 1; + rel1.relative: 0.9 0.3; + rel1.offset: 0 0; + rel2.relative: 1.0 0.7; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: right 0.0; + rel1.relative: 1.0 0.4; + rel1.offset: 0 0; + rel2.relative: 1.0 0.6; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: left 0.0; + rel1.relative: 0.2 0.2; + rel1.offset: 0 0; + rel2.relative: 0.8 0.8; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: full 0.0; + inherit: default 0.0; + visible: 0; + color: 255 255 255 0; + } + } + part + { + name: "center"; + type: SWALLOW; + mouse_events: 1; + description + { + state: default 0.0; + rel1.relative: 0.2 0.2; + rel1.offset: 0 0; + rel2.relative: 0.8 0.8; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: right 0.0; + rel1.relative: 0.9 0.3; + rel1.offset: 0 0; + rel2.relative: 1.0 0.7; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: left 0.0; + rel1.relative: 0.0 0.3; + rel1.offset: 0 0; + rel2.relative: 0.1 0.7; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: full 0.0; + rel1.relative: 0.0 0.0; + rel1.offset: 0 0; + rel2.relative: 1.0 1.0; + rel2.offset: -1 -1; + } + } + part + { + name: "offscreen_right"; + type: SWALLOW; + mouse_events: 1; + description + { + state: default 0.0; + visible: 0; + rel1.relative: 1.0 0.4; + rel1.offset: 0 0; + rel2.relative: 1.0 0.6; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: right 0.0; + visible: 0; + rel1.relative: 0.0 0.4; + rel1.offset: 0 0; + rel2.relative: 0.0 0.6; + rel2.offset: 0 0; + color: 255 255 255 255; + } + description + { + state: left 0.0; + visible: 1; + rel1.relative: 0.9 0.3; + rel1.offset: 0 0; + rel2.relative: 1.0 0.7; + rel2.offset: 0 0; + color: 255 255 255 255; + } + } + } + programs + { + program + { + name: "right"; + signal: "right"; + source: "ephoto"; + action: STATE_SET right 0.0; + transition: LINEAR 0.4; + target: "offscreen_left"; + target: "left"; + target: "center"; + target: "right"; + target: "offscreen_right"; + after: "done"; + } + program + { + name: "left"; + signal: "left"; + source: "ephoto"; + action: STATE_SET left 0.0; + transition: LINEAR 0.4; + target: "offscreen_left"; + target: "left"; + target: "center"; + target: "right"; + target: "offscreen_right"; + after: "done"; + } + program + { + name: "full"; + signal: "full"; + source: "ephoto"; + action: STATE_SET full 0.0; + transition: LINEAR 0.4; + target: "left"; + target: "right"; + target: "center"; + } + program + { + name: "full_reset"; + signal: "full_reset"; + source: "ephoto"; + action: STATE_SET default 0.0; + transition: LINEAR 0.4; + target: "left"; + target: "right"; + target: "center"; + } + program + { + name: "done"; + action: SIGNAL_EMIT "done" "ephoto"; + } + program + { + name: "reset"; + signal: "reset"; + source: "ephoto"; + action: STATE_SET default 0.0; + target: "offscreen_left"; + target: "left"; + target: "center"; + target: "right"; + target: "offscreen_right"; + } + } + } } diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 41f2885..f863650 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -16,12 +16,8 @@ endif _sources = \ ephoto.c \ ephoto_main.c \ - ephoto_config.c \ - ephoto_preferences.c \ - ephoto_thumb_browser.c \ - ephoto_flow_browser.c \ - ephoto_slideshow.c \ - ephoto_directory_thumb.c + ephoto_flow_browser.c \ + ephoto_thumb_browser.c _libs = @ELEMENTARY_LIBS@ @EFREET_MIME_LIBS@ @EIO_LIBS@ @EXIF_LIBS@ diff --git a/src/bin/ephoto.c b/src/bin/ephoto.c index b0b5cdc..a7898c8 100644 --- a/src/bin/ephoto.c +++ b/src/bin/ephoto.c @@ -1,15 +1,9 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#ifndef ELM_LIB_QUICKLAUNCH - #include "ephoto.h" -static void _ephoto_display_usage(void); +#ifndef ELM_LIB_QUICKLAUNCH -/* Global log domain pointer */ -int __log_domain = -1; +static void _ephoto_display_usage(void); +Ephoto *ephoto; EAPI int elm_main(int argc, char **argv) @@ -29,94 +23,86 @@ elm_main(int argc, char **argv) elm_need_ethumb(); elm_init(argc, argv); - elm_theme_extension_add(NULL, PACKAGE_DATA_DIR"/themes/default/ephoto.edj"); + elm_theme_extension_add(NULL, PACKAGE_DATA_DIR "/themes/default/ephoto.edj"); if (!efreet_mime_init()) - fprintf(stderr, "Could not init efreet_mime!\n"); + printf("Ephoto could not init efreet_mime!\n"); client = elm_thumb_ethumb_client_get(); if (!client) { - ERR("could not get ethumb_client"); + printf("Ephoto could not get ethumb_client; Terminating...\n"); r = 1; - goto end_log_domain; + goto end; } ethumb_client_crop_align_set(client, 0.5, 0.5); ethumb_client_aspect_set(client, ETHUMB_THUMB_CROP); ethumb_client_orientation_set(client, ETHUMB_THUMB_ORIENT_ORIGINAL); - __log_domain = eina_log_domain_register("ephoto", EINA_COLOR_ORANGE); - if (!__log_domain) - { - EINA_LOG_ERR("Could not register log domain: Ephoto"); - r = 1; - goto end_log_domain; - } elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); - DBG("Logging initialized"); + ephoto = calloc(1, sizeof(Ephoto)); + ephoto->client = client; + if (argc > 2) { - printf("Too Many Arguments!\n"); + printf("Too many arguments; Terminating...\n"); _ephoto_display_usage(); r = 1; goto end; } - else if (argc < 2) + if (argc == 2) { - Evas_Object *win = ephoto_window_add(NULL); - if (!win) + if (!strncmp(argv[1], "--help", 6) || !strncmp(argv[1], "-h", 2)) { - r = 1; + _ephoto_display_usage(); + r = 0; goto end; } + else if (argc == 2) + { + char *real = ecore_file_realpath(argv[1]); + if (!real) + { + printf("Invalid file or directory: '%s'; Terminating...\n", argv[1]); + r = 1; + goto end; + } + if (ecore_file_is_dir(real)) + ephoto->directory = eina_stringshare_add(real); + else if (ecore_file_exists(real)) + ephoto->file = eina_stringshare_add(real); + free(real); + } } - else if (!strncmp(argv[1], "--help", 6)) + + if (!ephoto_window_add()) { - _ephoto_display_usage(); - r = 0; + printf("Could not create the main window; Terminating...\n"); + r = 1; goto end; } - else - { - char *real = ecore_file_realpath(argv[1]); - if (!real) - { - printf("invalid file or directory: '%s'\n", argv[1]); - r = 1; - goto end; - } - Evas_Object *win = ephoto_window_add(real); - free(real); - if (!win) - { - r = 1; - goto end; - } - } elm_run(); end: - eina_log_domain_unregister(__log_domain); - end_log_domain: + if (ephoto) + free(ephoto); efreet_mime_shutdown(); elm_shutdown(); eio_shutdown(); - + return r; } -/*Display useage commands for ephoto*/ static void _ephoto_display_usage(void) { printf("Ephoto Usage: \n" - "ephoto --help : This page\n" - "ephoto filename : Specifies a file to open\n" - "ephoto dirname : Specifies a directory to open\n"); + "ephoto --help | -h : This page\n" + "ephoto filename : Specifies a file to open\n" + "ephoto directory : Specifies a directory to open\n"); } - #endif ELM_MAIN() diff --git a/src/bin/ephoto.h b/src/bin/ephoto.h index 7503714..60aefb7 100644 --- a/src/bin/ephoto.h +++ b/src/bin/ephoto.h @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -16,185 +15,68 @@ #include #include #include +#include #include #include #include #include #include -#define THEME_FILE PACKAGE_DATA_DIR"/themes/default/ephoto.edj" +/*Ephoto Typedefs*/ +typedef struct _Ephoto Ephoto; +typedef enum _Ephoto_State Ephoto_State; -typedef struct _Ephoto_Config Ephoto_Config; -typedef struct _Ephoto Ephoto; -typedef struct _Ephoto_Entry Ephoto_Entry; -typedef struct _Ephoto_Event_Entry_Create Ephoto_Event_Entry_Create; +/*Main Functions*/ +Evas_Object *ephoto_window_add(void); +void ephoto_title_set(const char *title); +void ephoto_thumb_size_set(int size); +void ephoto_directory_set(const char *path); -typedef enum _Ephoto_State Ephoto_State; -typedef enum _Ephoto_Orient Ephoto_Orient; +/*Main Children*/ +Evas_Object *ephoto_flow_browser_add(void); +void ephoto_flow_browser_image_set(void); +void ephoto_flow_browser_del(void); +void ephoto_flow_browser_show(void); -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); -void ephoto_directory_set(Ephoto *ephoto, const char *path); +Evas_Object *ephoto_slideshow_add(void); +void ephoto_slideshow_del(void); -Ephoto_Orient ephoto_file_orient_get(const char *path); - -Eina_Bool ephoto_config_init(Ephoto *em); -void ephoto_config_save(Ephoto *em, Eina_Bool instant); -void ephoto_config_free(Ephoto *em); - -Evas_Object *ephoto_flow_browser_add(Ephoto *ephoto, Evas_Object *parent); -void ephoto_flow_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry); -void ephoto_flow_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. - */ +Evas_Object *ephoto_thumb_browser_add(void); +void ephoto_thumb_browser_thumb_append(const char *file); +void ephoto_thumb_browser_del(void); +void ephoto_thumb_browser_show(void); +/*Ephoto States*/ enum _Ephoto_State { - EPHOTO_STATE_THUMB, - EPHOTO_STATE_FLOW, - EPHOTO_STATE_SLIDESHOW -}; - -enum _Ephoto_Orient /* matches with exif orientation tag */ -{ - EPHOTO_ORIENT_0 = 1, - EPHOTO_ORIENT_FLIP_HORIZ = 2, - EPHOTO_ORIENT_180 = 3, - EPHOTO_ORIENT_FLIP_VERT = 4, - EPHOTO_ORIENT_FLIP_VERT_90 = 5, - EPHOTO_ORIENT_90 = 6, - EPHOTO_ORIENT_FLIP_HORIZ_90 = 7, - EPHOTO_ORIENT_270 = 8 -}; - -/* 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; - const char *editor; - double slideshow_timeout; - const char *slideshow_transition; - - /* these should be per-window */ - int thumb_size; - int thumb_gen_size; - const char *directory; - + EPHOTO_STATE_THUMB, + EPHOTO_STATE_FLOW, + EPHOTO_STATE_SLIDESHOW }; +/*Ephoto Main Structure*/ struct _Ephoto { + /*Main Objects*/ Evas_Object *win; Evas_Object *bg; Evas_Object *pager; + /*Main Children*/ Evas_Object *thumb_browser; Evas_Object *flow_browser; Evas_Object *slideshow; - Eina_List *entries; - Eina_List *thumbs; /* live thumbs that need to be regenerated on changes */ - - int thumb_gen_size; /* pending value for thumb_regen */ - struct { - Ecore_Timer *thumb_regen; - } timer; - struct { - Ecore_Job *change_dir; - } job; - + /*Main Variables*/ + const char *directory; + const char *file; Eio_File *ls; - - Evas_Object *prefs_win; + Eina_List *images; + Eina_List *current_index; Ephoto_State state, prev_state; - - Ephoto_Config *config; + Ethumb_Client *client; }; -struct _Ephoto_Entry -{ - const char *path; - const char *basename; /* pointer inside path */ - const char *label; - Ephoto *ephoto; - Elm_Gengrid_Item *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 -{ - Ephoto_Entry *entry; -}; - -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); - -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__) - -static inline Eina_Bool -_ephoto_eina_file_direct_info_image_useful(const Eina_File_Direct_Info *info) -{ - const char /* *type, */ *bname, *ext; - - bname = info->path + info->name_start; - if (bname[0] == '.') return EINA_FALSE; - if ((info->type != EINA_FILE_REG) && (info->type != EINA_FILE_UNKNOWN)) - return EINA_FALSE; - - ext = info->path + info->path_length - 1; - for (; ext > bname; ext--) if (*ext == '.') break; - if (*ext == '.') - { - ext++; - if ((strcasecmp(ext, "jpg") == 0) || - (strcasecmp(ext, "jpeg") == 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; -} - -extern int EPHOTO_EVENT_ENTRY_CREATE; -extern int EPHOTO_EVENT_POPULATE_START; -extern int EPHOTO_EVENT_POPULATE_END; -extern int EPHOTO_EVENT_POPULATE_ERROR; +extern Ephoto *ephoto; #endif diff --git a/src/bin/ephoto_config.c b/src/bin/ephoto_config.c deleted file mode 100644 index 602e2f3..0000000 --- a/src/bin/ephoto_config.c +++ /dev/null @@ -1,158 +0,0 @@ -#include "ephoto.h" - -#define CONFIG_VERSION 5 - -static int _ephoto_config_load(Ephoto *ephoto); -static Eina_Bool _ephoto_on_config_save(void *data); - -static Eet_Data_Descriptor *edd = NULL; -static Ecore_Timer *save_timer = NULL; - -Eina_Bool -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))) - { - ERR("Unable to create the config data descriptor!"); - return EINA_FALSE; - } - - if (!edd) edd = eet_data_descriptor_stream_new(&eddc); -#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->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: - return EINA_TRUE; - } - - ephoto_config_save(ephoto, EINA_FALSE); - return EINA_TRUE; -} - -void -ephoto_config_save(Ephoto *ephoto, Eina_Bool instant) -{ - if (save_timer) - { - ecore_timer_del(save_timer); - save_timer = NULL; - } - - if (instant) - _ephoto_on_config_save(ephoto); - else - save_timer = ecore_timer_add(5.0, _ephoto_on_config_save, ephoto); -} - -void -ephoto_config_free(Ephoto *ephoto) -{ - free(ephoto->config); - ephoto->config = NULL; -} - -static int -_ephoto_config_load(Ephoto *ephoto) -{ - Eet_File *ef; - char buf[4096], buf2[4096]; - - snprintf(buf2, sizeof(buf2), "%s/.config/ephoto", getenv("HOME")); - ecore_file_mkpath(buf2); - snprintf(buf, sizeof(buf), "%s/ephoto.cfg", buf2); - - ef = eet_open(buf, EET_FILE_MODE_READ); - if (!ef) - { - ephoto_config_free(ephoto); - ephoto->config = calloc(1, sizeof(Ephoto_Config)); - return 0; - } - - ephoto->config = eet_data_read(ef, edd, "config"); - eet_close(ef); - - 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; -} - -static Eina_Bool -_ephoto_on_config_save(void *data) -{ - Ephoto *ephoto = data; - Eet_File *ef; - char buf[4096], buf2[4096]; - - snprintf(buf, sizeof(buf), "%s/.config/ephoto/ephoto.cfg", getenv("HOME")); - snprintf(buf2, sizeof(buf2), "%s.tmp", buf); - - ef = eet_open(buf2, EET_FILE_MODE_WRITE); - if (!ef) goto save_end; - - eet_data_write(ef, edd, "config", ephoto->config, 1); - if (eet_close(ef)) goto save_end; - - if (!ecore_file_mv(buf2, buf)) goto save_end; - - INF("Config saved"); - -save_end: - ecore_file_unlink(buf2); - - if (save_timer) - { - ecore_timer_del(save_timer); - save_timer = NULL; - } - - return ECORE_CALLBACK_CANCEL; -} diff --git a/src/bin/ephoto_directory_thumb.c b/src/bin/ephoto_directory_thumb.c deleted file mode 100644 index eeda248..0000000 --- a/src/bin/ephoto_directory_thumb.c +++ /dev/null @@ -1,176 +0,0 @@ -#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; -} diff --git a/src/bin/ephoto_flow_browser.c b/src/bin/ephoto_flow_browser.c index 9930438..72585bd 100644 --- a/src/bin/ephoto_flow_browser.c +++ b/src/bin/ephoto_flow_browser.c @@ -1,1028 +1,275 @@ #include "ephoto.h" -#ifdef HAVE_LIBEXIF -#include -#endif +static Evas_Object *_ephoto_add_image(const char *swallow); +static void _ephoto_flow_done(void *data __UNUSED__, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__); +static void _ephoto_flow_back(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__); +static void _ephoto_flow_prev(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__); +static void _ephoto_flow_next(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__); +static void _ephoto_center_image_clicked(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__); -/* ROTATION is disabled until we do it properly, and properly means - * 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 ZOOM_STEP 0.2 +typedef enum _Ephoto_Flow_State +{ + EPHOTO_FLOW_STATE_FLOW, + EPHOTO_FLOW_STATE_SINGLE +} Ephoto_Flow_State; typedef struct _Ephoto_Flow_Browser Ephoto_Flow_Browser; -typedef struct _Ephoto_Viewer Ephoto_Viewer; - struct _Ephoto_Flow_Browser { - Ephoto *ephoto; + Evas_Object *box; Evas_Object *layout; - Evas_Object *edje; - Evas_Object *orient_layout; - Evas_Object *orient_edje; - Evas_Object *viewer; + Evas_Object *images[5]; Evas_Object *toolbar; + Ephoto_Flow_State efs; struct { - Elm_Toolbar_Item *zoom_in; - Elm_Toolbar_Item *zoom_out; - Elm_Toolbar_Item *zoom_1; - Elm_Toolbar_Item *zoom_fit; - Elm_Toolbar_Item *go_first; + Elm_Toolbar_Item *go_back; Elm_Toolbar_Item *go_prev; Elm_Toolbar_Item *go_next; - Elm_Toolbar_Item *go_last; -#ifdef ROTATION - Elm_Toolbar_Item *rotate_counterclock; - Elm_Toolbar_Item *rotate_clock; - Elm_Toolbar_Item *flip_horiz; - Elm_Toolbar_Item *flip_vert; -#endif Elm_Toolbar_Item *slideshow; } action; - const char *pending_path; - Ephoto_Entry *entry; - Ephoto_Orient orient; - Eina_List *handlers; }; -struct _Ephoto_Viewer +Ephoto_Flow_Browser *efb; + +Evas_Object * +ephoto_flow_browser_add(void) { - Evas_Object *photocam; - Evas_Object *scroller; - Evas_Object *image; - double zoom; - Eina_Bool fit:1; -}; + efb = calloc(1, sizeof(Ephoto_Flow_Browser)); -static void _zoom_set(Ephoto_Flow_Browser *fb, double zoom); -static void _zoom_in(Ephoto_Flow_Browser *fb); -static void _zoom_out(Ephoto_Flow_Browser *fb); + efb->efs = EPHOTO_FLOW_STATE_FLOW; -static Eina_Bool -_path_is_jpeg(const char *path_stringshared) -{ - size_t len = eina_stringshare_strlen(path_stringshared); - const char *ext; + efb->box = elm_box_add(ephoto->win); + elm_box_horizontal_set(efb->box, EINA_FALSE); + elm_box_homogenous_set(efb->box, EINA_FALSE); + evas_object_size_hint_weight_set + (efb->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(ephoto->win, efb->box); + evas_object_show(efb->box); - if (len < sizeof(".jpg")) return EINA_FALSE; - ext = path_stringshared + len - (sizeof(".jpg") - 1); - if (strcasecmp(ext, ".jpg") == 0) return EINA_TRUE; + efb->toolbar = elm_toolbar_add(efb->box); + elm_toolbar_homogenous_set(efb->toolbar, EINA_TRUE); + elm_toolbar_mode_shrink_set(efb->toolbar, ELM_TOOLBAR_SHRINK_MENU); + elm_toolbar_menu_parent_set(efb->toolbar, efb->box); + evas_object_size_hint_weight_set(efb->toolbar, 0.0, 0.0); + evas_object_size_hint_align_set(efb->toolbar, EVAS_HINT_FILL, 0.0); - if (len < sizeof(".jpeg")) return EINA_FALSE; - ext = path_stringshared + len - (sizeof(".jpeg") - 1); - if (strcasecmp(ext, ".jpeg") == 0) return EINA_TRUE; + efb->action.go_back = elm_toolbar_item_append + (efb->toolbar, "edit-undo", "Back", _ephoto_flow_back, NULL); + elm_toolbar_item_priority_set(efb->action.go_back, 0); + efb->action.go_prev = elm_toolbar_item_append + (efb->toolbar, "go-previous", "Previous", _ephoto_flow_prev, NULL); + elm_toolbar_item_priority_set(efb->action.go_prev, 1); + efb->action.go_next = elm_toolbar_item_append + (efb->toolbar, "go-next", "Next", _ephoto_flow_next, NULL); + elm_toolbar_item_priority_set(efb->action.go_next, 2); + efb->action.slideshow = elm_toolbar_item_append + (efb->toolbar, "media-playback-start", "Slideshow", NULL, NULL); + elm_toolbar_item_priority_set(efb->action.slideshow, 3); - return EINA_FALSE; + elm_toolbar_icon_size_set(efb->toolbar, 32); + elm_box_pack_end(efb->box, efb->toolbar); + evas_object_show(efb->toolbar); + + efb->layout = elm_layout_add(ephoto->win); + elm_layout_file_set + (efb->layout, PACKAGE_DATA_DIR "/themes/default/ephoto.edj", "flow"); + evas_object_size_hint_weight_set + (efb->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_fill_set + (efb->layout, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_win_resize_object_add(ephoto->win, efb->layout); + elm_box_pack_end(efb->box, efb->layout); + evas_object_show(efb->layout); + edje_object_signal_callback_add + (elm_layout_edje_get(efb->layout), "done", "ephoto", _ephoto_flow_done, NULL); + + efb->images[0] = _ephoto_add_image("offscreen_left"); + efb->images[1] = _ephoto_add_image("left"); + efb->images[2] = _ephoto_add_image("center"); + evas_object_event_callback_add + (efb->images[2], EVAS_CALLBACK_MOUSE_DOWN, _ephoto_center_image_clicked, NULL); + efb->images[3] = _ephoto_add_image("right"); + efb->images[4] = _ephoto_add_image("offscreen_right"); + + return efb->box; } -static void -_viewer_photocam_loaded(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +void +ephoto_flow_browser_image_set(void) { - elm_photocam_paused_set(obj, EINA_FALSE); + Eina_List *prevv, *prev, *next, *nextt; + + prev = eina_list_prev(ephoto->current_index); + if (!eina_list_data_get(prev)) + prev = eina_list_last(ephoto->images); + prevv = eina_list_prev(prev); + if (!eina_list_data_get(prevv)) + prevv = eina_list_last(ephoto->images); + next = eina_list_next(ephoto->current_index); + if (!eina_list_data_get(next)) + next = eina_list_nth_list(ephoto->images, 0); + nextt = eina_list_next(next); + if (!eina_list_data_get(nextt)) + nextt = eina_list_nth_list(ephoto->images, 0); + + elm_bg_file_set(efb->images[0], eina_list_data_get(prevv), NULL); + elm_bg_file_set(efb->images[1], eina_list_data_get(prev), NULL); + elm_bg_file_set(efb->images[2], eina_list_data_get(ephoto->current_index), NULL); + elm_bg_file_set(efb->images[3], eina_list_data_get(next), NULL); + elm_bg_file_set(efb->images[4], eina_list_data_get(nextt), NULL); } -static void -_viewer_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +void +ephoto_flow_browser_del(void) { - Ephoto_Viewer *v = data; - free(v); + evas_object_del(efb->box); + free(efb); +} + +void +ephoto_flow_browser_show(void) +{ + ephoto->prev_state = ephoto->state; + ephoto->state = EPHOTO_STATE_FLOW; + + ephoto_flow_browser_image_set(); + elm_pager_content_promote(ephoto->pager, ephoto->flow_browser); } static Evas_Object * -_viewer_add(Evas_Object *parent, const char *path) +_ephoto_add_image(const char *swallow) { - Ephoto_Viewer *v = calloc(1, sizeof(Ephoto_Viewer)); - Evas_Object *obj; - int err; + Evas_Object *o; - EINA_SAFETY_ON_NULL_RETURN_VAL(v, NULL); - if (_path_is_jpeg(path)) + o = elm_bg_add(efb->box); + elm_layout_content_set(efb->layout, swallow, o); + evas_object_show(o); + + return o; +} + +static void +_ephoto_flow_done(void *data __UNUSED__, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Evas_Object *edje; + Eina_List *prevv, *prev, *next, *nextt; + + prev = eina_list_prev(ephoto->current_index); + if (!eina_list_data_get(prev)) + prev = eina_list_last(ephoto->images); + prevv = eina_list_prev(prev); + if (!eina_list_data_get(prevv)) + prevv = eina_list_last(ephoto->images); + next = eina_list_next(ephoto->current_index); + if (!eina_list_data_get(next)) + next = eina_list_nth_list(ephoto->images, 0); + nextt = eina_list_next(next); + if (!eina_list_data_get(nextt)) + nextt = eina_list_nth_list(ephoto->images, 0); + + edje = elm_layout_edje_get(efb->layout); + edje_object_freeze(edje); + + elm_bg_file_set(efb->images[0], eina_list_data_get(prevv), NULL); + elm_layout_content_unset(efb->layout, "offscreen_left"); + elm_layout_content_set(efb->layout, "offscreen_left", efb->images[0]); + elm_bg_file_set(efb->images[1], eina_list_data_get(prev), NULL); + elm_layout_content_unset(efb->layout, "left"); + elm_layout_content_set(efb->layout, "left", efb->images[1]); + elm_bg_file_set(efb->images[2], eina_list_data_get(ephoto->current_index), NULL); + elm_layout_content_unset(efb->layout, "center"); + elm_layout_content_set(efb->layout, "center", efb->images[2]); + elm_bg_file_set(efb->images[3], eina_list_data_get(next), NULL); + elm_layout_content_unset(efb->layout, "right"); + elm_layout_content_set(efb->layout, "right", efb->images[3]); + elm_bg_file_set(efb->images[4], eina_list_data_get(nextt), NULL); + elm_layout_content_unset(efb->layout, "offscreen_right"); + elm_layout_content_set(efb->layout, "offscreen_right", efb->images[4]); + + edje_object_signal_emit(edje, "reset", "ephoto"); + edje_object_thaw(edje); + + elm_toolbar_item_disabled_set(efb->action.go_prev, EINA_FALSE); + elm_toolbar_item_disabled_set(efb->action.go_next, EINA_FALSE); +} + +static void +_ephoto_flow_back(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) +{ + elm_toolbar_item_selected_set + (elm_toolbar_selected_item_get(efb->toolbar), EINA_FALSE); + + ephoto_thumb_browser_show(); +} + +static void +_ephoto_flow_prev(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *edje; + + elm_toolbar_item_selected_set + (elm_toolbar_selected_item_get(efb->toolbar), EINA_FALSE); + + ephoto->current_index = eina_list_prev(ephoto->current_index); + if (!eina_list_data_get(ephoto->current_index)) + ephoto->current_index = eina_list_last(ephoto->images); + + elm_toolbar_item_disabled_set(efb->action.go_prev, EINA_TRUE); + elm_toolbar_item_disabled_set(efb->action.go_next, EINA_TRUE); + + edje = elm_layout_edje_get(efb->layout); + + if (efb->efs == EPHOTO_FLOW_STATE_SINGLE) { - 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; - elm_photocam_paused_set(obj, EINA_TRUE); - evas_object_smart_callback_add - (obj, "loaded", _viewer_photocam_loaded, v); + edje_object_signal_emit(edje, "full_reset", "ephoto"); + efb->efs = EPHOTO_FLOW_STATE_FLOW; + } + + edje_object_signal_emit(edje, "right", "ephoto"); +} + +static void +_ephoto_flow_next(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *edje; + + elm_toolbar_item_selected_set + (elm_toolbar_selected_item_get(efb->toolbar), EINA_FALSE); + + ephoto->current_index = eina_list_next(ephoto->current_index); + if (!ephoto->current_index) + ephoto->current_index = eina_list_nth_list(ephoto->images, 0); + + elm_toolbar_item_disabled_set(efb->action.go_prev, EINA_TRUE); + elm_toolbar_item_disabled_set(efb->action.go_next, EINA_TRUE); + + edje = elm_layout_edje_get(efb->layout); + + if (efb->efs == EPHOTO_FLOW_STATE_SINGLE) + { + edje_object_signal_emit(edje, "full_reset", "ephoto"); + efb->efs = EPHOTO_FLOW_STATE_FLOW; + } + + edje_object_signal_emit(edje, "left", "ephoto"); +} + +static void +_ephoto_center_image_clicked(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *edje; + + edje = elm_layout_edje_get(efb->layout); + + if (efb->efs == EPHOTO_FLOW_STATE_FLOW) + { + edje_object_signal_emit(edje, "full", "ephoto"); + efb->efs = EPHOTO_FLOW_STATE_SINGLE; } else { - Evas_Coord w, h; - obj = v->scroller = elm_scroller_add(parent); - EINA_SAFETY_ON_NULL_GOTO(obj, error); - 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_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_scroller_content_set(obj, v->image); - } - - 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); - evas_object_data_set(obj, "viewer", v); - evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _viewer_del, v); - return obj; - - load_error: - ERR("could not load image '%s': %s", path, evas_load_error_str(err)); - evas_object_del(obj); - error: - free(v); - return NULL; -} - -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); - else - { - Evas_Coord w, h; - evas_object_image_size_get(v->image, &w, &h); - w *= zoom; - h *= zoom; - evas_object_size_hint_min_set(v->image, w, h); - evas_object_size_hint_max_set(v->image, w, h); + edje_object_signal_emit(edje, "full_reset", "ephoto"); + efb->efs = EPHOTO_FLOW_STATE_FLOW; } } -static void -_viewer_zoom_fit_apply(Ephoto_Viewer *v) -{ - Evas_Coord cw, ch, iw, ih; - double zx, zy, zoom; - - if (v->photocam) - { - evas_object_geometry_get(v->photocam, NULL, NULL, &cw, &ch); - elm_photocam_image_size_get(v->photocam, &iw, &ih); - } - else - { - evas_object_geometry_get(v->scroller, NULL, NULL, &cw, &ch); - evas_object_image_size_get(v->image, &iw, &ih); - } - - if ((cw <= 0) || (ch <= 0)) return; /* object still not resized */ - EINA_SAFETY_ON_TRUE_RETURN(iw <= 0); - EINA_SAFETY_ON_TRUE_RETURN(ih <= 0); - - zx = (double)cw / (double)iw; - zy = (double)ch / (double)ih; - - zoom = (zx < zy) ? zx : zy; - _viewer_zoom_apply(v, zoom); -} - -static void -_viewer_resized(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) -{ - _viewer_zoom_fit_apply(data); -} - -static void -_viewer_zoom_set(Evas_Object *obj, double zoom) -{ - Ephoto_Viewer *v = evas_object_data_get(obj, "viewer"); - EINA_SAFETY_ON_NULL_RETURN(v); - _viewer_zoom_apply(v, zoom); - - if (v->fit) - { - if (v->photocam) - evas_object_event_callback_del_full - (v->photocam, EVAS_CALLBACK_RESIZE, _viewer_resized, v); - else - evas_object_event_callback_del_full - (v->scroller, EVAS_CALLBACK_RESIZE, _viewer_resized, v); - v->fit = EINA_FALSE; - } -} - -static double -_viewer_zoom_get(Evas_Object *obj) -{ - Ephoto_Viewer *v = evas_object_data_get(obj, "viewer"); - EINA_SAFETY_ON_NULL_RETURN_VAL(v, 0.0); - return v->zoom; -} - -static void -_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); - else - evas_object_event_callback_add - (v->scroller, EVAS_CALLBACK_RESIZE, _viewer_resized, v); - - _viewer_zoom_fit_apply(v); -} - -static void -_orient_apply(Ephoto_Flow_Browser *fb) -{ -#ifdef ROTATION - const char *sig; - switch (fb->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'", fb->orient, sig); - edje_object_signal_emit(fb->orient_edje, sig, "ephoto"); -#else - (void)fb; -#endif -} - -#ifdef ROTATION -static void -_rotate_counterclock(Ephoto_Flow_Browser *fb) -{ - switch (fb->orient) - { - case EPHOTO_ORIENT_0: - fb->orient = EPHOTO_ORIENT_270; - break; - case EPHOTO_ORIENT_90: - fb->orient = EPHOTO_ORIENT_0; - break; - case EPHOTO_ORIENT_180: - fb->orient = EPHOTO_ORIENT_90; - break; - case EPHOTO_ORIENT_270: - fb->orient = EPHOTO_ORIENT_180; - break; - case EPHOTO_ORIENT_FLIP_HORIZ: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90; - break; - case EPHOTO_ORIENT_FLIP_VERT: - fb->orient = EPHOTO_ORIENT_FLIP_VERT_90; - break; - case EPHOTO_ORIENT_FLIP_HORIZ_90: - fb->orient = EPHOTO_ORIENT_FLIP_VERT; - break; - case EPHOTO_ORIENT_FLIP_VERT_90: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ; - break; - } - _orient_apply(fb); -} - -static void -_rotate_clock(Ephoto_Flow_Browser *fb) -{ - switch (fb->orient) - { - case EPHOTO_ORIENT_0: - fb->orient = EPHOTO_ORIENT_90; - break; - case EPHOTO_ORIENT_90: - fb->orient = EPHOTO_ORIENT_180; - break; - case EPHOTO_ORIENT_180: - fb->orient = EPHOTO_ORIENT_270; - break; - case EPHOTO_ORIENT_270: - fb->orient = EPHOTO_ORIENT_0; - break; - case EPHOTO_ORIENT_FLIP_HORIZ: - fb->orient = EPHOTO_ORIENT_FLIP_VERT_90; - break; - case EPHOTO_ORIENT_FLIP_VERT: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90; - break; - case EPHOTO_ORIENT_FLIP_HORIZ_90: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ; - break; - case EPHOTO_ORIENT_FLIP_VERT_90: - fb->orient = EPHOTO_ORIENT_FLIP_VERT; - break; - } - _orient_apply(fb); -} - -static void -_flip_horiz(Ephoto_Flow_Browser *fb) -{ - switch (fb->orient) - { - case EPHOTO_ORIENT_0: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ; - break; - case EPHOTO_ORIENT_90: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90; - break; - case EPHOTO_ORIENT_180: - fb->orient = EPHOTO_ORIENT_FLIP_VERT; - break; - case EPHOTO_ORIENT_270: - fb->orient = EPHOTO_ORIENT_FLIP_VERT_90; - break; - case EPHOTO_ORIENT_FLIP_HORIZ: - fb->orient = EPHOTO_ORIENT_0; - break; - case EPHOTO_ORIENT_FLIP_VERT: - fb->orient = EPHOTO_ORIENT_180; - break; - case EPHOTO_ORIENT_FLIP_HORIZ_90: - fb->orient = EPHOTO_ORIENT_90; - break; - case EPHOTO_ORIENT_FLIP_VERT_90: - fb->orient = EPHOTO_ORIENT_270; - break; - } - _orient_apply(fb); -} - -static void -_flip_vert(Ephoto_Flow_Browser *fb) -{ - switch (fb->orient) - { - case EPHOTO_ORIENT_0: - fb->orient = EPHOTO_ORIENT_FLIP_VERT; - break; - case EPHOTO_ORIENT_90: - fb->orient = EPHOTO_ORIENT_FLIP_VERT_90; - break; - case EPHOTO_ORIENT_180: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ; - break; - case EPHOTO_ORIENT_270: - fb->orient = EPHOTO_ORIENT_FLIP_HORIZ_90; - break; - case EPHOTO_ORIENT_FLIP_HORIZ: - fb->orient = EPHOTO_ORIENT_180; - break; - case EPHOTO_ORIENT_FLIP_VERT: - fb->orient = EPHOTO_ORIENT_0; - break; - case EPHOTO_ORIENT_FLIP_HORIZ_90: - fb->orient = EPHOTO_ORIENT_270; - break; - case EPHOTO_ORIENT_FLIP_VERT_90: - fb->orient = EPHOTO_ORIENT_90; - break; - } - _orient_apply(fb); -} -#endif - -static void -_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info) -{ - Ephoto_Flow_Browser *fb = data; - Evas_Event_Mouse_Wheel *ev = event_info; - if (!evas_key_modifier_is_set(ev->modifiers, "Control")) return; - - if (ev->z > 0) _zoom_in(fb); - else _zoom_out(fb); -} - -static Ephoto_Entry * -_first_entry_find(Ephoto_Flow_Browser *fb) -{ - const Eina_List *l; - Ephoto_Entry *entry; - EINA_SAFETY_ON_NULL_RETURN_VAL(fb->ephoto, NULL); - - EINA_LIST_FOREACH(fb->ephoto->entries, l, entry) - if (!entry->is_dir) return entry; - return NULL; -} - -static Ephoto_Entry * -_last_entry_find(Ephoto_Flow_Browser *fb) -{ - const Eina_List *l; - Ephoto_Entry *entry; - EINA_SAFETY_ON_NULL_RETURN_VAL(fb->ephoto, NULL); - - EINA_LIST_REVERSE_FOREACH(fb->ephoto->entries, l, entry) - if (!entry->is_dir) return entry; - return NULL; -} - -static void -_ephoto_flow_browser_toolbar_eval(Ephoto_Flow_Browser *fb) -{ - if (!fb->entry) - { - elm_toolbar_item_disabled_set(fb->action.go_first, EINA_TRUE); - elm_toolbar_item_disabled_set(fb->action.go_prev, EINA_TRUE); - elm_toolbar_item_disabled_set(fb->action.go_next, EINA_TRUE); - elm_toolbar_item_disabled_set(fb->action.go_last, EINA_TRUE); - elm_toolbar_item_disabled_set(fb->action.slideshow, EINA_TRUE); - } - else - { - Eina_Bool is_first = fb->entry == _first_entry_find(fb); - Eina_Bool is_last = fb->entry == _last_entry_find(fb); - - elm_toolbar_item_disabled_set(fb->action.go_first, is_first); - elm_toolbar_item_disabled_set(fb->action.go_prev, is_first); - elm_toolbar_item_disabled_set(fb->action.go_next, is_last); - elm_toolbar_item_disabled_set(fb->action.go_last, is_last); - elm_toolbar_item_disabled_set(fb->action.slideshow, EINA_FALSE); - } -} - -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_flow_browser_recalc(Ephoto_Flow_Browser *fb) -{ - if (fb->viewer) - { - evas_object_del(fb->viewer); - fb->viewer = NULL; - } - - if (fb->entry) - { - const char *bname = ecore_file_file_get(fb->entry->path); - fb->viewer = _viewer_add(fb->orient_layout, fb->entry->path); - elm_layout_content_set - (fb->orient_layout, "elm.swallow.content", fb->viewer); - evas_object_show(fb->viewer); - evas_object_event_callback_add - (fb->viewer, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel, fb); - edje_object_part_text_set(fb->edje, "elm.text.title", bname); - ephoto_title_set(fb->ephoto, bname); - fb->orient = ephoto_file_orient_get(fb->entry->path); - _orient_apply(fb); - } - - elm_object_focus(fb->layout); - - _ephoto_flow_browser_toolbar_eval(fb); -} - -static void -_zoom_set(Ephoto_Flow_Browser *fb, double zoom) -{ - DBG("zoom %f", zoom); - if (zoom <= 0.0) return; - _viewer_zoom_set(fb->viewer, zoom); -} - -static void -_zoom_fit(Ephoto_Flow_Browser *fb) -{ - if (fb->viewer) _viewer_zoom_fit(fb->viewer); -} - -static void -_zoom_in(Ephoto_Flow_Browser *fb) -{ - double change = (1.0 + ZOOM_STEP); - _viewer_zoom_set(fb->viewer, _viewer_zoom_get(fb->viewer) * change); -} - -static void -_zoom_out(Ephoto_Flow_Browser *fb) -{ - double change = (1.0 - ZOOM_STEP); - _viewer_zoom_set(fb->viewer, _viewer_zoom_get(fb->viewer) * change); -} - -static void -_zoom_in_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.zoom_in, EINA_FALSE); - _zoom_in(fb); -} - -static void -_zoom_out_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.zoom_out, EINA_FALSE); - _zoom_out(fb); -} - -static void -_zoom_1_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.zoom_1, EINA_FALSE); - _zoom_set(fb, 1.0); -} - -static void -_zoom_fit_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.zoom_fit, EINA_FALSE); - _zoom_fit(fb); -} - -static int -_entry_cmp(const void *pa, const void *pb) -{ - const Ephoto_Entry *a = pa; - const char *path = pb; - - if (path == a->path) - return 0; - else - return strcoll(a->path, path); -} - -static void -_next_entry(Ephoto_Flow_Browser *fb) -{ - Ephoto_Entry *entry = NULL; - Eina_List *node; - EINA_SAFETY_ON_NULL_RETURN(fb->entry); - - node = eina_list_search_sorted_list(fb->ephoto->entries, _entry_cmp, fb->entry->path); - if (!node) return; - while ((node = node->next)) - { - entry = node->data; - if (!entry->is_dir) - break; - } - if (!entry) - entry = _first_entry_find(fb); - if (entry) - { - DBG("next is '%s'", entry->path); - ephoto_flow_browser_entry_set(fb->layout, entry); - } -} - -static void -_prev_entry(Ephoto_Flow_Browser *fb) -{ - Eina_List *node; - Ephoto_Entry *entry = NULL; - EINA_SAFETY_ON_NULL_RETURN(fb->entry); - - node = eina_list_search_sorted_list(fb->ephoto->entries, _entry_cmp, fb->entry->path); - if (!node) return; - while ((node = node->prev)) - { - entry = node->data; - if (!entry->is_dir) - break; - } - if (!entry) - entry = _last_entry_find(fb); - if (entry) - { - DBG("prev is '%s'", entry->path); - ephoto_flow_browser_entry_set(fb->layout, entry); - } -} - -static void -_first_entry(Ephoto_Flow_Browser *fb) -{ - Ephoto_Entry *entry = _first_entry_find(fb); - if (!entry) return; - DBG("first is '%s'", entry->path); - ephoto_flow_browser_entry_set(fb->layout, entry); -} - -static void -_last_entry(Ephoto_Flow_Browser *fb) -{ - Ephoto_Entry *entry = _last_entry_find(fb); - if (!entry) return; - DBG("last is '%s'", entry->path); - ephoto_flow_browser_entry_set(fb->layout, entry); -} - -static void -_go_first(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.go_first, EINA_FALSE); - _first_entry(fb); -} - -static void -_go_prev(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.go_prev, EINA_FALSE); - _prev_entry(fb); -} - -static void -_go_next(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.go_next, EINA_FALSE); - _next_entry(fb); -} - -static void -_go_last(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.go_last, EINA_FALSE); - _last_entry(fb); -} - -#ifdef ROTATION -static void -_go_rotate_counterclock(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.rotate_counterclock, EINA_FALSE); - _rotate_counterclock(fb); -} - -static void -_go_rotate_clock(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.rotate_clock, EINA_FALSE); - _rotate_clock(fb); -} - -static void -_go_flip_horiz(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.flip_horiz, EINA_FALSE); - _flip_horiz(fb); -} - -static void -_go_flip_vert(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.flip_vert, EINA_FALSE); - _flip_vert(fb); -} -#endif - -static void -_slideshow(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - elm_toolbar_item_selected_set(fb->action.slideshow, EINA_FALSE); - if (fb->entry) - evas_object_smart_callback_call(fb->layout, "slideshow", fb->entry); -} - -static void -_back(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - evas_object_smart_callback_call(fb->layout, "back", fb->entry); -} - -static void -_key_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info) -{ - Ephoto_Flow_Browser *fb = data; - Evas_Event_Key_Down *ev = event_info; - Eina_Bool ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); - 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"))) - _zoom_in(fb); - else if (!strcmp(k, "minus")) - _zoom_out(fb); - else if (!strcmp(k, "0")) - { - if (shift) _zoom_fit(fb); - else _zoom_set(fb, 1.0); - } - - return; - } - - if (!strcmp(k, "Escape")) - evas_object_smart_callback_call(fb->layout, "back", fb->entry); - else if (!strcmp(k, "Left") || !strcmp(k, "BackSpace")) - _prev_entry(fb); - else if (!strcmp(k, "Right") || !strcmp(k, "space")) - _next_entry(fb); - else if (!strcmp(k, "Home")) - _first_entry(fb); - else if (!strcmp(k, "End")) - _last_entry(fb); -#if ROTATION - else if (!strcmp(k, "bracketleft")) - { - if (!shift) _rotate_counterclock(fb); - else _flip_horiz(fb); - } - else if (!strcmp(k, "bracketright")) - { - if (!shift) _rotate_clock(fb); - else _flip_vert(fb); - } -#endif - else if (!strcmp(k, "F5")) - { - if (fb->entry) - evas_object_smart_callback_call(fb->layout, "slideshow", fb->entry); - } -} - -static void -_entry_free(void *data, const Ephoto_Entry *entry __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - fb->entry = NULL; -} - -static void -_layout_del(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - Ecore_Event_Handler *handler; - - EINA_LIST_FREE(fb->handlers, handler) - ecore_event_handler_del(handler); - if (fb->entry) - ephoto_entry_free_listener_del(fb->entry, _entry_free, fb); - if (fb->pending_path) - eina_stringshare_del(fb->pending_path); - free(fb); -} - -static Elm_Toolbar_Item * -_toolbar_item_add(Ephoto_Flow_Browser *fb, const char *icon, const char *label, int priority, Evas_Smart_Cb cb) -{ - Elm_Toolbar_Item *item = elm_toolbar_item_append(fb->toolbar, icon, label, - cb, fb); - elm_toolbar_item_priority_set(item, priority); - return item; -} - -static Elm_Toolbar_Item * -_toolbar_item_separator_add(Ephoto_Flow_Browser *fb) -{ - Elm_Toolbar_Item *it = elm_toolbar_item_append - (fb->toolbar, NULL, NULL, NULL, NULL); - elm_toolbar_item_separator_set(it, EINA_TRUE); - return it; -} - -static Eina_Bool -_ephoto_flow_populate_end(void *data, int type __UNUSED__, void *event __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - - _ephoto_flow_browser_toolbar_eval(fb); - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_ephoto_flow_entry_create(void *data, int type __UNUSED__, void *event __UNUSED__) -{ - Ephoto_Flow_Browser *fb = data; - Ephoto_Event_Entry_Create *ev = event; - Ephoto_Entry *e; - - e = ev->entry; - if (!fb->entry && fb->pending_path && e->path == fb->pending_path) - { - DBG("Adding entry %p for path %s", e, fb->pending_path); - - eina_stringshare_del(fb->pending_path); - fb->pending_path = NULL; - ephoto_flow_browser_entry_set(fb->ephoto->flow_browser, e); - } - - return ECORE_CALLBACK_PASS_ON; -} - -Evas_Object * -ephoto_flow_browser_add(Ephoto *ephoto, Evas_Object *parent) -{ - Evas_Object *layout = elm_layout_add(parent); - Ephoto_Flow_Browser *fb; - - EINA_SAFETY_ON_NULL_RETURN_VAL(layout, NULL); - - fb = calloc(1, sizeof(Ephoto_Flow_Browser)); - EINA_SAFETY_ON_NULL_GOTO(fb, error); - fb->ephoto = ephoto; - fb->layout = layout; - fb->edje = elm_layout_edje_get(layout); - evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, _layout_del, fb); - evas_object_event_callback_add - (layout, EVAS_CALLBACK_KEY_DOWN, _key_down, fb); - evas_object_data_set(layout, "flow_browser", fb); - - edje_object_signal_callback_add(fb->edje, "elm,action,back", "", _back, fb); - - if (!elm_layout_theme_set - (layout, "layout", "application", "toolbar-content-back")) - { - ERR("could not load style 'toolbar-content-back' from theme"); - goto error; - } - - fb->toolbar = edje_object_part_external_object_get - (fb->edje, "elm.external.toolbar"); - if (!fb->toolbar) - { - ERR("no toolbar in layout!"); - goto error; - } - elm_toolbar_homogenous_set(fb->toolbar, EINA_FALSE); - elm_toolbar_mode_shrink_set(fb->toolbar, ELM_TOOLBAR_SHRINK_MENU); - elm_toolbar_menu_parent_set(fb->toolbar, parent); - - fb->action.slideshow = _toolbar_item_add - (fb, "media-playback-start", "Slideshow", 150, _slideshow); - - fb->action.zoom_in = _toolbar_item_add - (fb, "zoom-in", "Zoom In", 100, _zoom_in_cb); - fb->action.zoom_out = _toolbar_item_add - (fb, "zoom-out", "Zoom Out", 80, _zoom_out_cb); - fb->action.zoom_1 = _toolbar_item_add - (fb, "zoom-original", "Zoom 1:1", 50, _zoom_1_cb); - fb->action.zoom_fit = _toolbar_item_add - (fb, "zoom-fit-best", "Zoom Fit", 40, _zoom_fit_cb); - - _toolbar_item_separator_add(fb); - - fb->action.go_first = _toolbar_item_add(fb, "go-first", "First", 50, _go_first); - fb->action.go_prev = _toolbar_item_add - (fb, "go-previous", "Previous", 100, _go_prev); - fb->action.go_next = _toolbar_item_add(fb, "go-next", "Next", 50, _go_next); - fb->action.go_last = _toolbar_item_add(fb, "go-last", "Last", 50, _go_last); - - _toolbar_item_separator_add(fb); - -#ifdef ROTATION - fb->action.rotate_counterclock = _toolbar_item_add - (fb, "object-rotate-left", "Rotate Left", 50, _go_rotate_counterclock); - fb->action.rotate_clock = _toolbar_item_add - (fb, "object-rotate-right", "Rotate Right", 30, _go_rotate_clock); - fb->action.flip_horiz = _toolbar_item_add - (fb, "object-flip-horizontal", "Flip Horiz.", 30, _go_flip_horiz); - fb->action.flip_vert = _toolbar_item_add - (fb, "object-flip-vertical", "Flip Vert.", 30, _go_flip_vert); - - elm_toolbar_item_tooltip_text_set - (fb->action.rotate_counterclock, - "Rotate object to the left (counter-clockwise)"); - elm_toolbar_item_tooltip_text_set - (fb->action.rotate_clock, "Rotate object to the right (clockwise)"); - - elm_toolbar_item_tooltip_text_set - (fb->action.flip_horiz, "Flip object horizontally"); - elm_toolbar_item_tooltip_text_set - (fb->action.flip_vert, "Flip object vertically"); -#endif - - fb->orient_layout = elm_layout_add(layout); - if (!elm_layout_theme_set - (fb->orient_layout, "layout", "ephoto", "orient")) - { - ERR("could not load style 'ephoto/orient' from theme"); - goto error; - } - fb->orient_edje = elm_layout_edje_get(fb->orient_layout); - elm_layout_content_set(fb->layout, "elm.swallow.content", fb->orient_layout); - elm_object_focus_custom_chain_append(fb->layout, fb->orient_layout, NULL); - - _ephoto_flow_browser_toolbar_eval(fb); - - fb->handlers = eina_list_append - (fb->handlers, ecore_event_handler_add - (EPHOTO_EVENT_POPULATE_END, _ephoto_flow_populate_end, fb)); - - fb->handlers = eina_list_append - (fb->handlers, ecore_event_handler_add - (EPHOTO_EVENT_ENTRY_CREATE, _ephoto_flow_entry_create, fb)); - - return layout; - - error: - evas_object_del(layout); - return NULL; -} - -void -ephoto_flow_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry) -{ - Ephoto_Flow_Browser *fb = evas_object_data_get(obj, "flow_browser"); - Eina_Bool same_file = EINA_FALSE; - EINA_SAFETY_ON_NULL_RETURN(fb); - - DBG("entry %p, was %p", entry, fb->entry); - - if (fb->entry) - { - ephoto_entry_free_listener_del(fb->entry, _entry_free, fb); - if (entry && entry->path == fb->entry->path) - same_file = EINA_TRUE; - } - - fb->entry = entry; - - if (entry) - ephoto_entry_free_listener_add(entry, _entry_free, fb); - - if (!fb->entry || same_file) - _ephoto_flow_browser_toolbar_eval(fb); - else - { - _ephoto_flow_browser_recalc(fb); - _zoom_fit(fb); - } -} - -void -ephoto_flow_browser_path_pending_set(Evas_Object *obj, const char *path) -{ - Ephoto_Flow_Browser *fb = evas_object_data_get(obj, "flow_browser"); - EINA_SAFETY_ON_NULL_RETURN(fb); - - DBG("Setting pending path '%s'", path); - fb->pending_path = eina_stringshare_add(path); -} diff --git a/src/bin/ephoto_main.c b/src/bin/ephoto_main.c index 3c99720..9470c73 100644 --- a/src/bin/ephoto_main.c +++ b/src/bin/ephoto_main.c @@ -1,160 +1,23 @@ #include "ephoto.h" -int EPHOTO_EVENT_ENTRY_CREATE = 0; -int EPHOTO_EVENT_POPULATE_START = 0; -int EPHOTO_EVENT_POPULATE_END = 0; -int EPHOTO_EVENT_POPULATE_ERROR = 0; - -typedef struct _Ephoto_Entry_Free_Listener Ephoto_Entry_Free_Listener; -struct _Ephoto_Entry_Free_Listener -{ - void (*cb)(void *data, const Ephoto_Entry *dead); - const void *data; -}; - -static void -_ephoto_state_set(Ephoto *ephoto, Ephoto_State state) -{ - ephoto->prev_state = ephoto->state; - ephoto->state = state; -} - -static void -_ephoto_thumb_browser_show(Ephoto *ephoto, Ephoto_Entry *entry) -{ - DBG("entry '%s'", entry ? entry->path : ""); - - ephoto_flow_browser_entry_set(ephoto->flow_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_flow_browser_show(Ephoto *ephoto, Ephoto_Entry *entry) -{ - DBG("entry '%s'", entry->path); - ephoto_flow_browser_entry_set(ephoto->flow_browser, entry); - elm_pager_content_promote(ephoto->pager, ephoto->flow_browser); - _ephoto_state_set(ephoto, EPHOTO_STATE_FLOW); -} - -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_flow_browser_back(void *data, Evas_Object *obj __UNUSED__, void *event_info) -{ - Ephoto *ephoto = data; - Ephoto_Entry *entry = event_info; - _ephoto_thumb_browser_show(ephoto, entry); -} - -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_FLOW: - _ephoto_flow_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_flow_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_flow_browser_entry_set(ephoto->flow_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_flow_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 -_win_free(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto *ephoto = data; - if (ephoto->timer.thumb_regen) ecore_timer_del(ephoto->timer.thumb_regen); - free(ephoto); -} +static void _ephoto_window_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__); +static void _ephoto_thumb_populate(void); +static Eina_Bool _ephoto_thumb_populate_filter(void *data __UNUSED__, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info); +static void _ephoto_thumb_populate_main(void *data __UNUSED__, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info); +static void _ephoto_thumb_populate_end(void *data __UNUSED__, Eio_File *handler __UNUSED__); +static void _ephoto_thumb_populate_error(void *data __UNUSED__, Eio_File *handler __UNUSED__, int error); Evas_Object * -ephoto_window_add(const char *path) +ephoto_window_add(void) { - Ephoto *ephoto = calloc(1, sizeof(Ephoto)); - Ethumb_Client *client = elm_thumb_ethumb_client_get(); - char buf[PATH_MAX]; - EINA_SAFETY_ON_NULL_RETURN_VAL(ephoto, NULL); - - 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(); - ephoto->win = elm_win_add(NULL, "ephoto", ELM_WIN_BASIC); if (!ephoto->win) - { - free(ephoto); - return NULL; - } - - evas_object_event_callback_add - (ephoto->win, EVAS_CALLBACK_FREE, _win_free, ephoto); - - elm_win_autodel_set(ephoto->win, EINA_TRUE); - - if (!ephoto_config_init(ephoto)) - { - 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)) - ephoto_thumb_size_set(ephoto, ephoto->config->thumb_size); - else if (client) - ethumb_client_size_set - (client, ephoto->config->thumb_gen_size, ephoto->config->thumb_gen_size); + return NULL; + evas_object_resize(ephoto->win, 600, 400); + ephoto_title_set("Ephoto - Picture Enlightenment"); + evas_object_smart_callback_add + (ephoto->win, "delete,request", _ephoto_window_del, NULL); + evas_object_show(ephoto->win); ephoto->bg = elm_bg_add(ephoto->win); evas_object_size_hint_weight_set @@ -164,7 +27,7 @@ ephoto_window_add(const char *path) evas_object_show(ephoto->bg); ephoto->pager = elm_pager_add(ephoto->win); - elm_object_style_set(ephoto->pager, "fade_invisible"); + elm_object_style_set(ephoto->pager, "fade"); evas_object_size_hint_weight_set (ephoto->pager, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_fill_set @@ -172,372 +35,101 @@ ephoto_window_add(const char *path) elm_win_resize_object_add(ephoto->win, ephoto->pager); evas_object_show(ephoto->pager); - ephoto->thumb_browser = ephoto_thumb_browser_add(ephoto, ephoto->pager); - if (!ephoto->thumb_browser) - { - ERR("could not add thumb browser"); - evas_object_del(ephoto->win); - 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->flow_browser = ephoto_flow_browser_add(ephoto, ephoto->pager); - if (!ephoto->flow_browser) - { - ERR("could not add flow browser"); - evas_object_del(ephoto->win); - return NULL; - } + ephoto->flow_browser = ephoto_flow_browser_add(); elm_pager_content_push(ephoto->pager, ephoto->flow_browser); - evas_object_smart_callback_add - (ephoto->flow_browser, "back", _ephoto_flow_browser_back, ephoto); - evas_object_smart_callback_add - (ephoto->flow_browser, "slideshow", - _ephoto_flow_browser_slideshow, ephoto); - ephoto->slideshow = ephoto_slideshow_add(ephoto, ephoto->pager); - if (!ephoto->slideshow) + ephoto->thumb_browser = ephoto_thumb_browser_add(); + elm_pager_content_push(ephoto->pager, ephoto->thumb_browser); + + elm_pager_content_promote(ephoto->pager, ephoto->thumb_browser); + ephoto->state = EPHOTO_STATE_THUMB; + + if (!ephoto->directory && !ephoto->file) { - ERR("could not add flow browser"); - evas_object_del(ephoto->win); - return NULL; + char buf[PATH_MAX], *cwd; + cwd = getcwd(buf, PATH_MAX); + ephoto->directory = eina_stringshare_add(cwd); } - elm_pager_content_push(ephoto->pager, ephoto->slideshow); - evas_object_smart_callback_add - (ephoto->slideshow, "back", _ephoto_slideshow_back, ephoto); + else if (ephoto->file) + ephoto->directory = eina_stringshare_add(ecore_file_dir_get(ephoto->file)); - if ((!path) || (!ecore_file_exists(path))) - { - path = ephoto->config->directory; - if ((path) && (!ecore_file_exists(path))) path = NULL; - if (!path) - { - if (getcwd(buf, sizeof(buf))) - path = buf; - else - path = getenv("HOME"); - } - } - - if (ecore_file_is_dir(path)) - { - ephoto_directory_set(ephoto, path); - _ephoto_thumb_browser_show(ephoto, NULL); - } - else - { - char *dir = ecore_file_dir_get(path); - ephoto_directory_set(ephoto, dir); - free(dir); - ephoto_flow_browser_path_pending_set(ephoto->flow_browser, path); - - elm_pager_content_promote(ephoto->pager, ephoto->flow_browser); - ephoto->state = EPHOTO_STATE_FLOW; - } - - /* TODO restore size from last run as well? */ - evas_object_resize(ephoto->win, 900, 600); - evas_object_show(ephoto->win); + ephoto->current_index = ephoto->images; + _ephoto_thumb_populate(); return ephoto->win; } void -ephoto_title_set(Ephoto *ephoto, const char *title) +ephoto_title_set(const char *title) { - char buf[1024] = "Ephoto"; - - if (title) snprintf(buf, sizeof(buf), "%s - Ephoto", title); - elm_win_title_set(ephoto->win, buf); -} - -static int -_entry_cmp(const void *pa, const void *pb) -{ - const Ephoto_Entry *a = pa, *b = pb; - if (a->is_dir == b->is_dir) - return strcoll(a->basename, b->basename); - else if (a->is_dir) - return -1; - else - return 1; + elm_win_title_set(ephoto->win, title); } static void -_ephoto_populate_main(void *data, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info) +_ephoto_window_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__) { - Ephoto *ephoto = data; - Ephoto_Entry *e; - Ephoto_Event_Entry_Create *ev; + ephoto_thumb_browser_del(); + ephoto_flow_browser_del(); + evas_object_del(ephoto->win); +} - 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; - - ecore_event_add(EPHOTO_EVENT_ENTRY_CREATE, ev, NULL, NULL); +static void +_ephoto_thumb_populate(void) +{ + ephoto->ls = eio_file_stat_ls(ephoto->directory, + _ephoto_thumb_populate_filter, + _ephoto_thumb_populate_main, + _ephoto_thumb_populate_end, + _ephoto_thumb_populate_error, + NULL); } static Eina_Bool -_ephoto_populate_filter(void *data __UNUSED__, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info) +_ephoto_thumb_populate_filter(void *data __UNUSED__, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info) { - const char *bname = info->path + info->name_start; + const char *bname = info->path + info->name_start, *ext; if (bname[0] == '.') return EINA_FALSE; - if (info->type == EINA_FILE_DIR) return EINA_TRUE; - - return _ephoto_eina_file_direct_info_image_useful(info); -} - -static void -_ephoto_populate_end(void *data, Eio_File *handler __UNUSED__) -{ - Ephoto *ephoto = data; - ephoto->ls = NULL; - - ecore_event_add(EPHOTO_EVENT_POPULATE_END, NULL, NULL, NULL); -} - -static void -_ephoto_populate_error(void *data, Eio_File *handler, int error) -{ - Ephoto *ephoto = data; - if (error) ERR("could not populate: %s", strerror(error)); - - /* XXX: Perhaps it would be better to _not_ emit POPULATE_END here */ - ecore_event_add(EPHOTO_EVENT_POPULATE_ERROR, NULL, NULL, NULL); - _ephoto_populate_end(ephoto, handler); -} - -static void -_ephoto_populate_entries(Ephoto *ephoto) -{ - /* Edje_External_Param param; */ - DBG("populate from '%s'", ephoto->config->directory); - - ephoto_entries_free(ephoto); - - ephoto->ls = eio_file_stat_ls(ephoto->config->directory, - _ephoto_populate_filter, - _ephoto_populate_main, - _ephoto_populate_end, - _ephoto_populate_error, - ephoto); - - ecore_event_add(EPHOTO_EVENT_POPULATE_START, NULL, NULL, NULL); -} - -static void -_ephoto_change_dir(void *data) -{ - Ephoto *ephoto = data; - ephoto->job.change_dir = NULL; - _ephoto_populate_entries(ephoto); -} - -void -ephoto_directory_set(Ephoto *ephoto, const char *path) -{ - EINA_SAFETY_ON_NULL_RETURN(ephoto); - - 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); -} - -static Eina_Bool -_thumb_gen_size_changed_timer_cb(void *data) -{ - Ephoto *ephoto = data; - Ethumb_Client *client; - const Eina_List *l; - Evas_Object *o; - - if (ephoto->config->thumb_gen_size == ephoto->thumb_gen_size) goto end; - - INF("thumbnail generation size changed from %d to %d", - ephoto->config->thumb_gen_size, ephoto->thumb_gen_size); - - client = elm_thumb_ethumb_client_get(); - if (!client) + if (info->type == EINA_FILE_DIR) return EINA_FALSE; + if ((info->type != EINA_FILE_REG) && (info->type != EINA_FILE_UNKNOWN)) + return EINA_FALSE; + ext = info->path + info->path_length - 1; + for (; ext > bname; ext--) if (*ext == '.') break; + if (*ext == '.') { - DBG("no client yet, try again later"); - return EINA_TRUE; + ext++; + if ((strcasecmp(ext, "jpeg") == 0) || + (strcasecmp(ext, "jpg") == 0) || + (strcasecmp(ext, "png") == 0) || + (strcasecmp(ext, "svg") == 0) || + (strcasecmp(ext, "gif") == 0)) + return EINA_TRUE; } - - ephoto->config->thumb_gen_size = ephoto->thumb_gen_size; - ethumb_client_size_set - (client, ephoto->thumb_gen_size, ephoto->thumb_gen_size); - - EINA_LIST_FOREACH(ephoto->thumbs, l, o) - { - Ethumb_Thumb_Format format; - format = (long)evas_object_data_get(o, "ephoto_format"); - ethumb_client_format_set(client, format); - elm_thumb_reload(o); - } - - end: - ephoto->timer.thumb_regen = NULL; return EINA_FALSE; } -void -ephoto_thumb_size_set(Ephoto *ephoto, int size) +static void +_ephoto_thumb_populate_main(void *data __UNUSED__, Eio_File *handler __UNUSED__, const Eina_File_Direct_Info *info) { - if (ephoto->config->thumb_size != size) - { - INF("thumbnail display size changed from %d to %d", - ephoto->config->thumb_size, size); - ephoto->config->thumb_size = size; - ephoto_config_save(ephoto, EINA_FALSE); - } + ephoto->images = eina_list_append(ephoto->images, info->path); - if (size <= 128) ephoto->thumb_gen_size = 128; - else if (size <= 256) ephoto->thumb_gen_size = 256; - else ephoto->thumb_gen_size = 512; - - if (ephoto->timer.thumb_regen) ecore_timer_del(ephoto->timer.thumb_regen); - ephoto->timer.thumb_regen = ecore_timer_add - (0.1, _thumb_gen_size_changed_timer_cb, ephoto); + ephoto_thumb_browser_thumb_append(info->path); + if (ephoto->file && !strcmp(ephoto->file, info->path)) + ephoto->current_index = ephoto->images; } static void -_thumb_del(void *data, Evas *e __UNUSED__, Evas_Object *o, void *event_info __UNUSED__) +_ephoto_thumb_populate_end(void *data __UNUSED__, Eio_File *handler __UNUSED__) { - Ephoto *ephoto = data; - ephoto->thumbs = eina_list_remove(ephoto->thumbs, o); + ephoto->ls = NULL; + if (!ephoto->current_index) + ephoto->current_index = eina_list_nth_list(ephoto->images, 0); } -Evas_Object * -ephoto_thumb_add(Ephoto *ephoto, Evas_Object *parent, const char *path) +static void +_ephoto_thumb_populate_error(void *data __UNUSED__, Eio_File *handler __UNUSED__, int error) { - Evas_Object *o; - - EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); - - o = elm_thumb_add(parent); - if (!o) return NULL; - - if (path) ephoto_thumb_path_set(o, path); - elm_object_style_set(o, "noframe"); - ephoto->thumbs = eina_list_append(ephoto->thumbs, o); - evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _thumb_del, ephoto); - return o; + if (error) + printf("Error while populating images: %s\n", strerror(error)); } -void -ephoto_thumb_path_set(Evas_Object *o, const char *path) -{ - Ethumb_Thumb_Format format = ETHUMB_THUMB_FDO; - const char *ext = strrchr(path, '.'); - if (ext) - { - ext++; - if ((strcasecmp(ext, "jpg") == 0) || - (strcasecmp(ext, "jpeg") == 0)) - format = ETHUMB_THUMB_JPEG; /* faster! */ - } - - ethumb_client_format_set(elm_thumb_ethumb_client_get(), format); - evas_object_data_set(o, "ephoto_format", (void*)(long)format); - elm_thumb_file_set(o, path, NULL); -} - -Ephoto_Entry * -ephoto_entry_new(Ephoto *ephoto, const char *path, const char *label) -{ - Ephoto_Entry *entry; - EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); - entry = calloc(1, sizeof(Ephoto_Entry)); - EINA_SAFETY_ON_NULL_RETURN_VAL(entry, NULL); - entry->ephoto = ephoto; - entry->path = eina_stringshare_add(path); - entry->basename = ecore_file_file_get(entry->path); - entry->label = eina_stringshare_add(label); - return entry; -} - -void -ephoto_entry_free(Ephoto_Entry *entry) -{ - const char *s; - Ephoto_Entry_Free_Listener *fl; - - EINA_LIST_FREE(entry->free_listeners, fl) - { - fl->cb((void *)fl->data, entry); - free(fl); - } - 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); -} - -void -ephoto_entry_free_listener_add(Ephoto_Entry *entry, void (*cb)(void *data, const Ephoto_Entry *entry), const void *data) -{ - Ephoto_Entry_Free_Listener *fl; - EINA_SAFETY_ON_NULL_RETURN(entry); - EINA_SAFETY_ON_NULL_RETURN(cb); - fl = malloc(sizeof(Ephoto_Entry_Free_Listener)); - EINA_SAFETY_ON_NULL_RETURN(fl); - fl->cb = cb; - fl->data = data; - entry->free_listeners = eina_list_append(entry->free_listeners, fl); -} - -void -ephoto_entry_free_listener_del(Ephoto_Entry *entry, void (*cb)(void *data, const Ephoto_Entry *entry), const void *data) -{ - Eina_List *l; - Ephoto_Entry_Free_Listener *fl; - EINA_SAFETY_ON_NULL_RETURN(entry); - EINA_SAFETY_ON_NULL_RETURN(cb); - EINA_LIST_FOREACH(entry->free_listeners, l, fl) - { - if ((fl->cb == cb) && (fl->data == data)) - { - entry->free_listeners = eina_list_remove_list - (entry->free_listeners, l); - break; - } - } -} - -void -ephoto_entries_free(Ephoto *ephoto) -{ - Ephoto_Entry *entry; - EINA_LIST_FREE(ephoto->entries, entry) ephoto_entry_free(entry); -} diff --git a/src/bin/ephoto_preferences.c b/src/bin/ephoto_preferences.c deleted file mode 100644 index a36c2d1..0000000 --- a/src/bin/ephoto_preferences.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "ephoto.h" - -#if 0 -static void _ephoto_preferences_pager_switch(void *data, Evas_Object *obj, void *event_info); -static void _ephoto_preferences_hide(void *data, Evas_Object *obj, void *event_info); -static void _ephoto_preferences_item_change(void *data, Evas_Object *obj, void *event_info); -static void _ephoto_preferences_slideshow_transition(void *data, Evas_Object *obj, void *event_info); - -static void -_ephoto_key_pressed(void *data, Evas *e, Evas_Object *obj, void *event_data) -{ - Evas_Event_Key_Down *eku; - eku = (Evas_Event_Key_Down *)event_data; - if (!strcmp(eku->key, "Escape")) - _ephoto_preferences_hide(data, NULL, NULL); -} - -void -ephoto_show_preferences(Ephoto *em) -{ - if (!em->prefs_win) - { - Evas_Object *o, *tb, *box, *pager, *pg1, *pg2, *pg3, *scr; - const Eina_List *transitions, *l; - const char *transition; - - em->prefs_win = o = elm_win_inwin_add(em->win); - elm_object_style_set(o, "minimal"); - - box = elm_box_add(em->prefs_win); - evas_object_show(box); - evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_win_inwin_content_set(o, box); - - tb = elm_toolbar_add(box); - elm_toolbar_homogenous_set(tb, EINA_FALSE); - evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.5); - - elm_box_pack_end(box, tb); - evas_object_show(tb); - - pager = elm_pager_add(box); - - pg1 = elm_box_add(pager); - evas_object_size_hint_weight_set(pg1, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(pg1); - elm_pager_content_push(pager, pg1); - evas_object_data_set(pg1, "pager", pager); - elm_toolbar_item_append(tb, NULL, "General", _ephoto_preferences_pager_switch, pg1); - - elm_box_pack_end(box, pager); - evas_object_show(pager); - - pg2 = elm_table_add(pager); - evas_object_size_hint_weight_set(pg2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(pg2); - elm_pager_content_push(pager, pg2); - evas_object_data_set(pg2, "pager", pager); - elm_toolbar_item_append(tb, NULL, "Slideshow", _ephoto_preferences_pager_switch, pg2); - - o = elm_label_add(pg2); - elm_label_label_set(o, "Delay:"); - evas_object_show(o); - elm_table_pack(pg2, o, 0, 0, 1, 1); - - o = elm_spinner_add(pg2); - elm_spinner_label_format_set(o, "%1.1f seconds"); - elm_spinner_step_set(o, 0.1); - elm_spinner_min_max_set(o, 1.0, 10.0); - elm_spinner_value_set(o, em->config->slideshow_timeout); - evas_object_data_set(o, "config", "slideshow_timeout"); - evas_object_smart_callback_add(o, "delay,changed", - _ephoto_preferences_item_change, em); - evas_object_show(o); - elm_table_pack(pg2, o, 1, 0, 1, 1); - - o = elm_label_add(pg2); - elm_label_label_set(o, "Transition:"); - evas_object_show(o); - elm_table_pack(pg2, o, 0, 1, 1, 1); - - o = elm_hoversel_add(pg2); - elm_hoversel_hover_parent_set(o, em->win); - elm_hoversel_label_set(o, em->config->slideshow_transition); - transitions = elm_slideshow_transitions_get(em->slideshow); - EINA_LIST_FOREACH(transitions, l, transition) - { - elm_hoversel_item_add(o, transition, NULL, ELM_ICON_NONE, _ephoto_preferences_slideshow_transition, em); - } - evas_object_show(o); - elm_table_pack(pg2, o, 1, 1, 1, 1); - - pg3 = elm_box_add(pager); - evas_object_size_hint_weight_set(pg3, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(pg3); - elm_pager_content_push(pager, pg3); - evas_object_data_set(pg3, "pager", pager); - elm_toolbar_item_append(tb, NULL, "External Editor", _ephoto_preferences_pager_switch, pg3); - - o = elm_label_add(pg3); - elm_label_label_set(o, "Image editor:"); - elm_box_pack_end(pg3, o); - evas_object_show(o); - - scr = elm_scroller_add(pg3); - elm_box_pack_end(pg3, scr); - elm_scroller_bounce_set(scr, EINA_TRUE, EINA_FALSE); - evas_object_size_hint_weight_set(scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(scr, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_show(scr); - - o = elm_entry_add(pg3); - elm_entry_single_line_set(o, EINA_TRUE); - evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_entry_entry_set(o, em->config->editor); - evas_object_data_set(o, "config", "editor"); - evas_object_smart_callback_add(o, "changed", - _ephoto_preferences_item_change, em); - elm_scroller_content_set(scr, o); - evas_object_show(o); - - o = elm_button_add(box); - elm_button_label_set(o, "Close"); - evas_object_size_hint_align_set(o, 1.0, 0.5); - evas_object_smart_callback_add(o, "clicked", _ephoto_preferences_hide, em); - elm_box_pack_end(box, o); - evas_object_show(o); - - - evas_object_event_callback_add(em->prefs_win, EVAS_CALLBACK_KEY_DOWN, - _ephoto_key_pressed, em); - - elm_toolbar_item_selected_set(elm_toolbar_first_item_get(tb), - EINA_TRUE); - elm_pager_content_promote(pager, pg1); - } - - elm_win_inwin_activate(em->prefs_win); - evas_object_focus_set(em->prefs_win, EINA_TRUE); -} - -static void -_ephoto_preferences_pager_switch(void *data, Evas_Object *obj, void *event_info) -{ - Evas_Object *o = data; - Evas_Object *pager = evas_object_data_get(o, "pager"); - - elm_pager_content_promote(pager, o); -} - -static void -_ephoto_preferences_item_change(void *data, Evas_Object *obj, void *event_info) -{ - Ephoto *em = data; - const char *key = evas_object_data_get(obj, "config"); - - if (!strcmp(key, "slideshow_timeout")) - em->config->slideshow_timeout = elm_spinner_value_get(obj); - else if (!strcmp(key, "editor")) - eina_stringshare_replace( - &em->config->editor, - eina_stringshare_add(elm_entry_entry_get(obj))); - - ephoto_config_save(em, EINA_FALSE); -} - -static void -_ephoto_preferences_slideshow_transition(void *data, Evas_Object *obj, void *event_info) -{ - Ephoto *em = data; - Elm_Hoversel_Item *it = event_info; - const char *transition = elm_hoversel_item_label_get(it); - - elm_hoversel_label_set(obj, transition); - em->config->slideshow_transition = transition; - ephoto_config_save(em, EINA_FALSE); -} - -static void -_ephoto_preferences_hide(void *data, Evas_Object *obj, void *event_info) -{ - Ephoto *em = data; - - evas_object_hide(em->prefs_win); - evas_object_focus_set(em->thumb_browser, EINA_TRUE); -} - -#endif diff --git a/src/bin/ephoto_thumb_browser.c b/src/bin/ephoto_thumb_browser.c index 4b3336f..70f6614 100644 --- a/src/bin/ephoto_thumb_browser.c +++ b/src/bin/ephoto_thumb_browser.c @@ -1,631 +1,190 @@ #include "ephoto.h" #define ZOOM_MAX 512 +#define ZOOM_MED 256 #define ZOOM_MIN 128 #define ZOOM_STEP 32 -#define TODO_ITEM_MIN_BATCH 16 +static Evas_Object *_ephoto_thumbnail_icon_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__); +static char *_ephoto_thumbnail_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__); +static void _ephoto_thumbnail_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__); +static void _ephoto_zoom_in(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__); +static void _ephoto_zoom_out(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__); +static void _ephoto_show_flow(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__); -#define PARENT_DIR "Up" +static const Elm_Gengrid_Item_Class _ephoto_thumbnail_class = { + "thumb", + { + _ephoto_thumbnail_label_get, + _ephoto_thumbnail_icon_get, + NULL, + _ephoto_thumbnail_del + } + }; typedef struct _Ephoto_Thumb_Browser Ephoto_Thumb_Browser; - struct _Ephoto_Thumb_Browser { - Ephoto *ephoto; - Evas_Object *layout; - Evas_Object *edje; - Evas_Object *fsel; + Evas_Object *box; Evas_Object *grid; - Evas_Object *dir_grid; Evas_Object *toolbar; - Evas_Object *overlay; - Eio_File *ls; - Eina_List *todo_items; - Eina_List *grid_items; - Eina_List *dir_grid_items; - Eina_List *handlers; + int thumb_size; struct { Elm_Toolbar_Item *zoom_in; Elm_Toolbar_Item *zoom_out; Elm_Toolbar_Item *view_flow; Elm_Toolbar_Item *slideshow; } action; - struct { - Ecore_Animator *todo_items; - } animator; - Eina_Bool layout_deleted : 1; }; -static void -_todo_items_free(Ephoto_Thumb_Browser *tb) +Ephoto_Thumb_Browser *etb; + +Evas_Object * +ephoto_thumb_browser_add(void) { - eina_list_free(tb->todo_items); - tb->todo_items = NULL; + etb = calloc(1, sizeof(Ephoto_Thumb_Browser)); + etb->thumb_size = ZOOM_MED; + + etb->box = elm_box_add(ephoto->win); + elm_box_horizontal_set(etb->box, EINA_FALSE); + elm_box_homogenous_set(etb->box, EINA_FALSE); + evas_object_size_hint_weight_set + (etb->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(ephoto->win, etb->box); + evas_object_show(etb->box); + + etb->toolbar = elm_toolbar_add(etb->box); + elm_toolbar_homogenous_set(etb->toolbar, EINA_TRUE); + elm_toolbar_mode_shrink_set(etb->toolbar, ELM_TOOLBAR_SHRINK_MENU); + elm_toolbar_menu_parent_set(etb->toolbar, etb->box); + evas_object_size_hint_weight_set(etb->toolbar, 0.0, 0.0); + evas_object_size_hint_align_set(etb->toolbar, EVAS_HINT_FILL, 0.0); + + etb->action.zoom_in = elm_toolbar_item_append + (etb->toolbar, "zoom-in", "Zoom In", _ephoto_zoom_in, NULL); + elm_toolbar_item_priority_set(etb->action.zoom_in, 0); + etb->action.zoom_out = elm_toolbar_item_append + (etb->toolbar, "zoom-out", "Zoom Out", _ephoto_zoom_out, NULL); + elm_toolbar_item_priority_set(etb->action.zoom_out, 1); + etb->action.view_flow = elm_toolbar_item_append + (etb->toolbar, "image", "View Flow", _ephoto_show_flow, NULL); + elm_toolbar_item_priority_set(etb->action.view_flow, 2); + etb->action.slideshow = elm_toolbar_item_append + (etb->toolbar, "media-playback-start", "Slideshow", NULL, NULL); + elm_toolbar_item_priority_set(etb->action.slideshow, 3); + + elm_toolbar_icon_size_set(etb->toolbar, 32); + elm_box_pack_end(etb->box, etb->toolbar); + evas_object_show(etb->toolbar); + + etb->grid = elm_gengrid_add(etb->box); + elm_gengrid_align_set(etb->grid, 0.5, 0.5); + elm_gengrid_bounce_set(etb->grid, EINA_FALSE, EINA_TRUE); + elm_gengrid_item_size_set(etb->grid, etb->thumb_size, etb->thumb_size); + evas_object_size_hint_align_set + (etb->grid, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set + (etb->grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_box_pack_end(etb->box, etb->grid); + evas_object_show(etb->grid); + + return etb->box; } -static void -_grid_items_free(Ephoto_Thumb_Browser *tb) +void +ephoto_thumb_browser_del(void) { - eina_list_free(tb->grid_items); - tb->grid_items = NULL; - eina_list_free(tb->dir_grid_items); - tb->dir_grid_items = NULL; + evas_object_del(etb->box); + free(etb); } -static Ephoto_Entry * -_first_file_entry_find(Ephoto_Thumb_Browser *tb) +void +ephoto_thumb_browser_show(void) { - const Eina_List *l; - Ephoto_Entry *entry; - EINA_LIST_FOREACH(tb->ephoto->entries, l, entry) - if (!entry->is_dir) return entry; - return NULL; + ephoto->prev_state = ephoto->state; + ephoto->state = EPHOTO_STATE_THUMB; + + elm_pager_content_promote(ephoto->pager, ephoto->thumb_browser); +} + +void +ephoto_thumb_browser_thumb_append(const char *file) +{ + const Elm_Gengrid_Item_Class *egic; + + egic = &_ephoto_thumbnail_class; + elm_gengrid_item_append(etb->grid, egic, file, NULL, NULL); +} + +static Evas_Object * +_ephoto_thumbnail_icon_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__) +{ + Ethumb_Thumb_Format format; + Evas_Object *o; + const char *file = data; + char *ext = strrchr(file, '.'); + + if ((strcasecmp(ext, "jpg") == 0) || + (strcasecmp(ext, "jpeg") == 0)) + format = ETHUMB_THUMB_JPEG; + else + format = ETHUMB_THUMB_FDO; + ethumb_client_format_set(ephoto->client, format); + ethumb_client_size_set(ephoto->client, etb->thumb_size, etb->thumb_size); + + o = elm_thumb_add(ephoto->win); + elm_object_style_set(o, "noframe"); + elm_thumb_file_set(o, file, NULL); + evas_object_show(o); + + return o; } static char * -_ephoto_thumb_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__) +_ephoto_thumbnail_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__) { - Ephoto_Entry *e = data; - return strdup(e->label); -} + const char *file = data, *f; -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; + f = ecore_file_file_get(file); - 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) - return ephoto_thumb_add(e->ephoto, obj, f); - - 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__) -{ - Ephoto_Entry *e = data; - return ephoto_thumb_add(e->ephoto, obj, e->path); + return strdup(f); } static void -_ephoto_thumb_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__) +_ephoto_thumbnail_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__) { - /* FIXME: the entry is already freed when changing directories - * One solution is to take care of this cleaning when manually removing - * some grid items - Ephoto_Entry *e = data; - e->item = NULL; - */ + } -static const Elm_Gengrid_Item_Class _ephoto_thumb_dir_class = { - "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", - { - _ephoto_thumb_item_label_get, - _ephoto_thumb_file_icon_get, - NULL, - _ephoto_thumb_item_del - } -}; - -static int -_entry_cmp(const void *pa, const void *pb) +static void +_ephoto_zoom_in(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) { - const Elm_Gengrid_Item *ia = pa; - const Ephoto_Entry *a, *b = pb; + elm_toolbar_item_selected_set(etb->action.zoom_in, EINA_FALSE); + etb->thumb_size += ZOOM_STEP; + if (etb->thumb_size >= ZOOM_MAX) + etb->thumb_size = ZOOM_MAX; + elm_gengrid_item_size_set(etb->grid, etb->thumb_size, etb->thumb_size); + elm_toolbar_item_disabled_set(etb->action.zoom_in, etb->thumb_size == ZOOM_MAX); + elm_toolbar_item_disabled_set(etb->action.zoom_out, etb->thumb_size == ZOOM_MIN); +} - 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 - return 1; +static void +_ephoto_zoom_out(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) +{ + elm_toolbar_item_selected_set(etb->action.zoom_out, EINA_FALSE); + etb->thumb_size -= ZOOM_STEP; + if (etb->thumb_size <= ZOOM_MIN) + etb->thumb_size = ZOOM_MIN; + elm_gengrid_item_size_set(etb->grid, etb->thumb_size, etb->thumb_size); + elm_toolbar_item_disabled_set(etb->action.zoom_out, etb->thumb_size == ZOOM_MIN); + elm_toolbar_item_disabled_set(etb->action.zoom_in, etb->thumb_size == ZOOM_MAX); } static void -_entry_item_add(Ephoto_Thumb_Browser *tb, Ephoto_Entry *e) +_ephoto_show_flow(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) { - const Elm_Gengrid_Item_Class *ic; - int near_cmp; - Evas_Object *grid_of_choice; - Elm_Gengrid_Item *near_item = NULL; - Eina_List *near_node = NULL, *list_of_choice = NULL; - - - if (e->is_dir) - { - ic = &_ephoto_thumb_dir_class; - grid_of_choice = tb->dir_grid; - list_of_choice = tb->dir_grid_items; - } - else - { - ic = &_ephoto_thumb_file_class; - grid_of_choice = tb->grid; - list_of_choice = tb->grid_items; - } + elm_toolbar_item_selected_set + (elm_toolbar_selected_item_get(etb->toolbar), EINA_FALSE); - near_node = eina_list_search_sorted_near_list - (list_of_choice, _entry_cmp, e, &near_cmp); - - if (near_node) - near_item = near_node->data; - - if (!near_item) - { - e->item = elm_gengrid_item_append(grid_of_choice, ic, e, NULL, NULL); - list_of_choice = eina_list_append(list_of_choice, e->item); - } - else - { - if (near_cmp < 0) - { - e->item = elm_gengrid_item_insert_after - (grid_of_choice, ic, e, near_item, NULL, NULL); - list_of_choice = eina_list_append_relative - (list_of_choice, e->item, near_item); - } - else - { - e->item = elm_gengrid_item_insert_before - (grid_of_choice, ic, e, near_item, NULL, NULL); - list_of_choice = eina_list_prepend_relative - (list_of_choice, e->item, near_item); - } - } - - if (e->item) - elm_gengrid_item_data_set(e->item, e); - else - { - ERR("could not add item to grid: path '%s'", e->path); - ephoto_entry_free(e); - return; - } -} - -static Eina_Bool -_todo_items_process(void *data) -{ - Ephoto_Thumb_Browser *tb = data; - Edje_Message_Int msg; - Ephoto_Entry *entry; - - if ((tb->ls) && (eina_list_count(tb->todo_items) < TODO_ITEM_MIN_BATCH)) - return EINA_TRUE; - - tb->animator.todo_items = NULL; - - EINA_LIST_FREE(tb->todo_items, entry) - _entry_item_add(tb, entry); - - msg.val = eina_list_count(tb->ephoto->entries); - edje_object_message_send(tb->edje, EDJE_MESSAGE_INT, 1, &msg); - - return EINA_FALSE; -} - -static void -_ephoto_thumb_selected(void *data, Evas_Object *o __UNUSED__, void *event_info) -{ - Ephoto_Thumb_Browser *tb = data; - Elm_Gengrid_Item *it = event_info; - Ephoto_Entry *e = elm_gengrid_item_data_get(it); - - elm_gengrid_item_selected_set(it, EINA_FALSE); - - if (e->is_dir) - ephoto_directory_set(tb->ephoto, e->path); - else - evas_object_smart_callback_call(tb->layout, "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 -_zoom_set(Ephoto_Thumb_Browser *tb, int zoom) -{ - if (zoom > ZOOM_MAX) zoom = ZOOM_MAX; - else if (zoom < ZOOM_MIN) zoom = ZOOM_MIN; - - ephoto_thumb_size_set(tb->ephoto, zoom); - elm_gengrid_item_size_set(tb->grid, zoom, zoom); - elm_gengrid_item_size_set(tb->dir_grid, zoom, zoom); - - elm_toolbar_item_disabled_set(tb->action.zoom_out, zoom == ZOOM_MIN); - elm_toolbar_item_disabled_set(tb->action.zoom_in, zoom == ZOOM_MAX); -} - -static void -_zoom_in(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Thumb_Browser *tb = data; - elm_toolbar_item_selected_set(tb->action.zoom_in, EINA_FALSE); - _zoom_set(tb, tb->ephoto->config->thumb_size + ZOOM_STEP); -} - -static void -_zoom_out(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Thumb_Browser *tb = data; - elm_toolbar_item_selected_set(tb->action.zoom_out, EINA_FALSE); - _zoom_set(tb, tb->ephoto->config->thumb_size - ZOOM_STEP); -} - -static void -_view_flow(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; - - elm_toolbar_item_selected_set(tb->action.view_flow, EINA_FALSE); - - 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->layout, "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; - - elm_toolbar_item_selected_set(tb->action.slideshow, EINA_FALSE); - - 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->layout, "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->layout, "slideshow", entry); - } -} - - -static void -_layout_del(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__) -{ - Ephoto_Thumb_Browser *tb = data; - Ecore_Event_Handler *handler; - - _todo_items_free(tb); - _grid_items_free(tb); - EINA_LIST_FREE(tb->handlers, handler) - ecore_event_handler_del(handler); - - if (tb->animator.todo_items) - { - ecore_animator_del(tb->animator.todo_items); - tb->animator.todo_items = NULL; - } - if (tb->ls) - { - tb->layout_deleted = EINA_TRUE; - eio_file_cancel(tb->ls); - return; - } - free(tb); -} - -static Elm_Toolbar_Item * -_toolbar_item_add(Ephoto_Thumb_Browser *tb, const char *icon, const char *label, int priority, Evas_Smart_Cb cb) -{ - Elm_Toolbar_Item *item = elm_toolbar_item_append(tb->toolbar, icon, label, - cb, tb); - elm_toolbar_item_priority_set(item, priority); - return item; -} - -static Eina_Bool -_ephoto_thumb_populate_start(void *data, int type __UNUSED__, void *event __UNUSED__) -{ - Ephoto_Thumb_Browser *tb = data; - - evas_object_smart_callback_call(tb->layout, "changed,directory", NULL); - - _todo_items_free(tb); - _grid_items_free(tb); - elm_gengrid_clear(tb->grid); - elm_gengrid_clear(tb->dir_grid); - elm_fileselector_entry_path_set(tb->fsel, tb->ephoto->config->directory); - - edje_object_signal_emit(tb->edje, "populate,start", "ephoto"); - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_ephoto_thumb_populate_end(void *data, int type __UNUSED__, void *event __UNUSED__) -{ - Ephoto_Thumb_Browser *tb = data; - - tb->ls = NULL; - if (tb->layout_deleted) - { - free(tb); - return ECORE_CALLBACK_PASS_ON; - } - - edje_object_signal_emit(tb->edje, "populate,stop", "ephoto"); - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_ephoto_thumb_populate_error(void *data, int type __UNUSED__, void *event __UNUSED__) -{ - Ephoto_Thumb_Browser *tb = data; - - edje_object_signal_emit(tb->edje, "populate,error", "ephoto"); - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_ephoto_thumb_entry_create(void *data, int type __UNUSED__, void *event) -{ - Ephoto_Thumb_Browser *tb = data; - Ephoto_Event_Entry_Create *ev = event; - Ephoto_Entry *e; - - e = ev->entry; - tb->todo_items = eina_list_append(tb->todo_items, e); - - if (!tb->animator.todo_items) - tb->animator.todo_items = ecore_animator_add(_todo_items_process, tb); - - return ECORE_CALLBACK_PASS_ON; -} - -static void -_ephoto_up_clicked(void *data, Evas_Object *obj, const char *emission, const char *source) -{ - Ephoto_Thumb_Browser *tb = data; - char *parent_dir; - - parent_dir = ecore_file_dir_get(tb->ephoto->config->directory); - if (!parent_dir) - return; - ephoto_directory_set(tb->ephoto, parent_dir); -} - -static void -_ephoto_dir_clicked(void *data, Evas_Object *obj, const char *emission, const char *source) -{ - Ephoto_Thumb_Browser *tb = data; - - evas_object_show(tb->dir_grid); -} - -Evas_Object * -ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent) -{ - Evas_Object *layout = elm_layout_add(parent); - Ephoto_Thumb_Browser *tb; - - EINA_SAFETY_ON_NULL_RETURN_VAL(layout, NULL); - - tb = calloc(1, sizeof(Ephoto_Thumb_Browser)); - EINA_SAFETY_ON_NULL_GOTO(tb, error); - tb->ephoto = ephoto; - tb->layout = layout; - tb->edje = elm_layout_edje_get(layout); - evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, _layout_del, tb); - evas_object_event_callback_add - (layout, EVAS_CALLBACK_KEY_DOWN, _key_down, tb); - evas_object_data_set(layout, "thumb_browser", tb); - - if (!elm_layout_theme_set - (layout, "layout", "application", "toolbar-vbox")) - { - ERR("could not load style 'toolbar-vbox' from theme"); - goto error; - } - - tb->toolbar = edje_object_part_external_object_get - (tb->edje, "elm.external.toolbar"); - if (!tb->toolbar) - { - ERR("no toolbar in layout!"); - goto error; - } - elm_toolbar_homogenous_set(tb->toolbar, EINA_FALSE); - elm_toolbar_mode_shrink_set(tb->toolbar, ELM_TOOLBAR_SHRINK_MENU); - elm_toolbar_menu_parent_set(tb->toolbar, parent); - - tb->action.slideshow = _toolbar_item_add - (tb, "media-playback-start", "Slideshow", 100, _slideshow); - tb->action.zoom_in = _toolbar_item_add - (tb, "zoom-in", "Zoom In", 50, _zoom_in); - tb->action.zoom_out = _toolbar_item_add - (tb, "zoom-out", "Zoom Out", 50, _zoom_out); - tb->action.view_flow = _toolbar_item_add - (tb, "image", "Larger", 50, _view_flow); - - tb->fsel = elm_fileselector_entry_add(layout); - 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_layout_box_append(layout, "elm.box.content", tb->fsel); - - tb->overlay = elm_layout_add(layout); - elm_layout_file_set - (tb->overlay, PACKAGE_DATA_DIR "/themes/default/ephoto.edj", - "ephoto,thumb,grid"); - evas_object_size_hint_weight_set - (tb->overlay, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set - (tb->overlay, EVAS_HINT_FILL, EVAS_HINT_FILL); - edje_object_signal_callback_add - (elm_layout_edje_get(tb->overlay), "ephoto.signal.up", "ephoto", - _ephoto_up_clicked, tb); - edje_object_signal_callback_add - (elm_layout_edje_get(tb->overlay), "ephoto.signal.dir", "ephoto", - _ephoto_dir_clicked, tb); - evas_object_show(tb->overlay); - elm_layout_box_append(tb->layout, "elm.box.content", tb->overlay); - - tb->grid = elm_gengrid_add(tb->overlay); - EINA_SAFETY_ON_NULL_GOTO(tb->grid, error); - 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_show(tb->grid); - elm_layout_content_set - (tb->overlay, "ephoto.swallow.content.thumb", tb->grid); - - tb->dir_grid = elm_gengrid_add(tb->overlay); - EINA_SAFETY_ON_NULL_GOTO(tb->dir_grid, error); - elm_gengrid_align_set(tb->dir_grid, 0.5, 0.5); - elm_gengrid_bounce_set(tb->dir_grid, EINA_FALSE, EINA_TRUE); - evas_object_size_hint_align_set - (tb->dir_grid, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set - (tb->dir_grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_smart_callback_add - (tb->dir_grid, "selected", _ephoto_thumb_selected, tb); - _zoom_set(tb, tb->ephoto->config->thumb_size); - evas_object_show(tb->dir_grid); - elm_layout_content_set - (tb->overlay, "ephoto.swallow.content.dir", tb->dir_grid); - - tb->handlers = eina_list_append - (tb->handlers, ecore_event_handler_add - (EPHOTO_EVENT_POPULATE_START, _ephoto_thumb_populate_start, tb)); - - tb->handlers = eina_list_append - (tb->handlers, ecore_event_handler_add - (EPHOTO_EVENT_POPULATE_END, _ephoto_thumb_populate_end, tb)); - - tb->handlers = eina_list_append - (tb->handlers, ecore_event_handler_add - (EPHOTO_EVENT_POPULATE_ERROR, _ephoto_thumb_populate_error, tb)); - - tb->handlers = eina_list_append - (tb->handlers, ecore_event_handler_add - (EPHOTO_EVENT_ENTRY_CREATE, _ephoto_thumb_entry_create, tb)); - - return layout; - - error: - evas_object_del(layout); - return NULL; + ephoto_flow_browser_show(); }