Ephoto: Implement history tracking and undo/redo options for the single browser.

This commit is contained in:
Stephen okra Houston 2016-08-05 12:29:39 -05:00
parent 1c01b4f315
commit 2d37951e95
2 changed files with 134 additions and 2 deletions

View File

@ -434,6 +434,9 @@ _config_bindings(Evas_Object *parent, Evas_Object *popup)
"<b>Ctrl+Shift+s:</b> Save Image As<br/>"
"<b>Ctrl+s:</b> Save Image<br/>"
"<b>Ctrl+u:</b> Reset Image<br/>"
"<b>Ctrl+y:</b> Redo<br/>"
"<b>Ctrl+Shift+z:</b> Redo<br/>"
"<b>Ctrl+z:</b> Undo<br/>"
"<b>Home:</b> Navigate First<br/>"
"<b>Left Arrow:</b> Navigate Previous<br/>"
"<b>Right Arrow:</b> Navigate Next<br/>"

View File

@ -6,6 +6,7 @@ static Ecore_Timer *_1s_hold = NULL;
typedef struct _Ephoto_Single_Browser Ephoto_Single_Browser;
typedef struct _Ephoto_Viewer Ephoto_Viewer;
typedef struct _Ephoto_History Ephoto_History;
struct _Ephoto_Single_Browser
{
@ -22,6 +23,8 @@ struct _Ephoto_Single_Browser
Ephoto_Orient orient;
Eina_List *handlers;
Eina_List *entries;
Eina_List *history;
unsigned int history_pos;
Eina_Bool editing:1;
Eina_Bool cropping:1;
unsigned int *edited_image_data;
@ -46,6 +49,13 @@ struct _Ephoto_Viewer
Ecore_Timer *anim_timer;
};
struct _Ephoto_History
{
unsigned int *im_data;
Evas_Coord w;
Evas_Coord h;
};
/*Common Callbacks*/
static const char *_ephoto_get_edje_group(const char *path);
static char *_ephoto_get_file_size(const char *path);
@ -820,6 +830,48 @@ _last_entry(Ephoto_Single_Browser *sb)
ephoto_single_browser_entry_set(sb->main, entry);
}
static void
_undo_image(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Ephoto_Single_Browser *sb = data;
Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer");
Ephoto_History *eh;
if (!v)
return;
if (sb->history && sb->history_pos > 0)
{
sb->history_pos--;
eh = eina_list_nth(sb->history, sb->history_pos);
evas_object_image_size_set(v->image, eh->w, eh->h);
evas_object_image_data_set(v->image, eh->im_data);
evas_object_image_data_update_add(v->image, 0, 0, eh->w, eh->h);
}
}
static void
_redo_image(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Ephoto_Single_Browser *sb = data;
Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer");
Ephoto_History *eh;
if (!v)
return;
if (sb->history && sb->history_pos < (eina_list_count(sb->history)-1))
{
sb->history_pos++;
eh = eina_list_nth(sb->history, sb->history_pos);
evas_object_image_size_set(v->image, eh->w, eh->h);
evas_object_image_data_set(v->image, eh->im_data);
evas_object_image_data_update_add(v->image, 0, 0, eh->w, eh->h);
}
}
static void
_reset_yes(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
@ -1398,7 +1450,6 @@ _viewer_add(Evas_Object *parent, const char *path, Ephoto_Single_Browser *sb)
v->anim_timer = ecore_timer_add(v->duration, _animate_cb, v);
}
v->monitor = eio_monitor_add(path);
v->monitor_handlers =
eina_list_append(v->monitor_handlers,
@ -1533,6 +1584,8 @@ _add_edit_menu_items(Ephoto_Single_Browser *sb, Evas_Object *menu)
menu_it =
elm_menu_item_add(menu, NULL, "document-properties", _("Edit"), NULL, NULL);
elm_menu_item_add(menu, menu_it, "edit-undo", _("Undo"), _undo_image, sb);
elm_menu_item_add(menu, menu_it, "edit-redo", _("Redo"), _redo_image, sb);
elm_menu_item_add(menu, menu_it, "edit-undo", _("Reset"), _reset_image, sb);
elm_menu_item_separator_add(menu, menu_it);
menu_itt =
@ -1686,6 +1739,17 @@ _ephoto_main_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNU
{
_reset_image(sb, NULL, NULL);
}
else if (!strcmp(k, "z"))
{
if (!shift)
_undo_image(sb, NULL, NULL);
else
_redo_image(sb, NULL, NULL);
}
else if (!strcmp(k, "y"))
{
_redo_image(sb, NULL, NULL);
}
return;
}
@ -1781,6 +1845,7 @@ _ephoto_main_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
Ecore_Event_Handler *handler;
Eina_Iterator *tmps;
Eina_File_Direct_Info *info;
Ephoto_History *eh;
EINA_LIST_FREE(sb->handlers, handler) ecore_event_handler_del(handler);
if (sb->entry)
@ -1796,6 +1861,17 @@ _ephoto_main_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
if (!strncmp(bname, "tmp", 3))
ecore_file_unlink(info->path);
}
if (sb->history)
{
EINA_LIST_FREE(sb->history, eh)
{
free(eh->im_data);
free(eh);
eh = NULL;
}
sb->history = NULL;
sb->history_pos = 0;
}
free(sb);
}
@ -1830,6 +1906,9 @@ void
ephoto_single_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry)
{
Ephoto_Single_Browser *sb = evas_object_data_get(obj, "single_browser");
Ephoto_Viewer *v;
Ephoto_History *eh;
Evas_Coord w, h;
char *dir;
if (sb->entry && !entry)
@ -1854,8 +1933,30 @@ ephoto_single_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry)
sb->ew = 0;
sb->eh = 0;
}
if (sb->history)
{
EINA_LIST_FREE(sb->history, eh)
{
free(eh->im_data);
free(eh);
eh = NULL;
}
sb->history = NULL;
sb->history_pos = 0;
}
if (sb->viewer)
_zoom_fit(sb);
{
v = evas_object_data_get(sb->viewer, "viewer");
evas_object_image_size_get(v->image, &w, &h);
eh = calloc(1, sizeof(Ephoto_History));
eh->im_data = malloc(sizeof(unsigned int) * w * h);
eh->im_data = memcpy(eh->im_data, evas_object_image_data_get(v->image, EINA_FALSE),
sizeof(unsigned int) * w * h);
eh->w = w;
eh->h = h;
sb->history = eina_list_append(sb->history, eh);
_zoom_fit(sb);
}
if (sb->event)
{
evas_object_del(sb->event);
@ -1938,6 +2039,8 @@ ephoto_single_browser_image_data_done(Evas_Object *main,
unsigned int *image_data, Evas_Coord w, Evas_Coord h)
{
Ephoto_Single_Browser *sb = evas_object_data_get(main, "single_browser");
Ephoto_History *eh;
Eina_List *l;
if (sb->editing)
{
@ -1952,6 +2055,30 @@ ephoto_single_browser_image_data_done(Evas_Object *main,
sb->edited_image_data = image_data;
sb->ew = w;
sb->eh = h;
if (sb->history_pos < (eina_list_count(sb->history)-1))
{
int count;
count = sb->history_pos + 1;
l = eina_list_nth_list(sb->history, count);
while (l)
{
eh = eina_list_data_get(l);
sb->history = eina_list_remove_list(sb->history, l);
free(eh->im_data);
free(eh);
eh = NULL;
l = eina_list_nth_list(sb->history, count);
}
}
eh = calloc(1, sizeof(Ephoto_History));
eh->im_data = malloc(sizeof(unsigned int) * sb->ew * sb->eh);
eh->im_data = memcpy(eh->im_data, sb->edited_image_data,
sizeof(unsigned int) * sb->ew * sb->eh);
eh->w = sb->ew;
eh->h = sb->eh;
sb->history = eina_list_append(sb->history, eh);
sb->history_pos = eina_list_count(sb->history) - 1;
_ephoto_update_bottom_bar(sb);
sb->editing = EINA_FALSE;
_zoom_fit(sb);
@ -2089,6 +2216,8 @@ ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent)
sb->editing = EINA_FALSE;
sb->cropping = EINA_FALSE;
sb->main = box;
sb->history = NULL;
sb->history_pos = 0;
elm_box_horizontal_set(sb->main, EINA_FALSE);
evas_object_event_callback_add(sb->main, EVAS_CALLBACK_DEL, _ephoto_main_del, sb);