summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2021-11-01 12:49:59 +0000
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2021-11-01 12:49:59 +0000
commit3bfb56367910811a2a84d25bd5a7a1357ee6e135 (patch)
tree9d984db1f366c0b7e37c6e5029352988e44e8770
parentc3189d60e78bdf8075d3b1c191571471e63f2161 (diff)
downloadenlightenment-3bfb56367910811a2a84d25bd5a7a1357ee6e135.tar.gz
paledit - add undo/redo with escape as undo
now you can rescue yourself from badness...
-rw-r--r--src/bin/tools/paledit/colsel.c5
-rw-r--r--src/bin/tools/paledit/main.c19
-rw-r--r--src/bin/tools/paledit/main.h20
-rw-r--r--src/bin/tools/paledit/meson.build3
-rw-r--r--src/bin/tools/paledit/palcols.c45
-rw-r--r--src/bin/tools/paledit/undoredo.c337
6 files changed, 427 insertions, 2 deletions
diff --git a/src/bin/tools/paledit/colsel.c b/src/bin/tools/paledit/colsel.c
index af5ecaba57..2ee92c45d8 100644
--- a/src/bin/tools/paledit/colsel.c
+++ b/src/bin/tools/paledit/colsel.c
@@ -12,6 +12,11 @@ _spinner_to_rect(Evas_Object *win)
{
Elm_Palette_Color *col = elm_object_item_data_get(it);
Elm_Palette *pal = evas_object_data_get(win, "pal");
+
+ undoredo_op_col_change(win, col->name,
+ col->r, col->g, col->b, col->a,
+ r, g, b, a);
+ elm_config_palette_color_set(pal, col->name, r, g, b, a);
col->r = r;
col->g = g;
col->b = b;
diff --git a/src/bin/tools/paledit/main.c b/src/bin/tools/paledit/main.c
index 0ddc07353b..d06139e4d2 100644
--- a/src/bin/tools/paledit/main.c
+++ b/src/bin/tools/paledit/main.c
@@ -19,6 +19,7 @@ pal_load(Evas_Object *win)
if (!palname) return;
Elm_Palette *pal = elm_config_palette_load(palname);
if (!pal) return;
+ undoredo_reset(win);
evas_object_data_set(win, "pal", pal);
palcols_fill(win);
palimg_update(evas_object_data_get(win, "pal_image"), pal);
@@ -32,6 +33,19 @@ _cb_close_click(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_
evas_object_del(data);
}
+static void
+_cb_key_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+ Evas_Object *win = data;
+ Evas_Event_Key_Down *ev = event_info;
+
+ if (!strcmp(ev->key, "Escape"))
+ {
+ underedo_undo(win);
+ }
+}
+
+
EAPI_MAIN int
elm_main(int argc, char **argv)
{
@@ -42,6 +56,11 @@ elm_main(int argc, char **argv)
win = elm_win_util_standard_add("e_paledit", "Palette Editor");
elm_win_autodel_set(win, EINA_TRUE);
+ o = evas_object_rectangle_add(evas_object_evas_get(win));
+ if (!evas_object_key_grab(o, "Escape", 0, 0, EINA_FALSE)) printf("Can't grab...\n");
+ evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN,
+ _cb_key_down, win);
+
fr = o = elm_frame_add(win);
elm_object_style_set(o, "pad_medium");
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
diff --git a/src/bin/tools/paledit/main.h b/src/bin/tools/paledit/main.h
index 1578aa8eaf..1b0d98b874 100644
--- a/src/bin/tools/paledit/main.h
+++ b/src/bin/tools/paledit/main.h
@@ -17,4 +17,24 @@ Evas_Object *colsel_add(Evas_Object *win);
void pal_load(Evas_Object *win);
void pal_save(Evas_Object *win);
+void
+undoredo_op_col_add(Evas_Object *win,
+ const char *col,
+ int r, int g, int b, int a);
+void
+undoredo_op_col_del(Evas_Object *win,
+ const char *col,
+ int r, int g, int b, int a);
+void
+undoredo_op_col_change(Evas_Object *win,
+ const char *col,
+ int r_from, int g_from, int b_from, int a_from,
+ int r_to, int g_to, int b_to, int a_to);
+void
+undoredo_reset(Evas_Object *win);
+void
+underedo_undo(Evas_Object *win);
+void
+underedo_redo(Evas_Object *win);
+
#endif
diff --git a/src/bin/tools/paledit/meson.build b/src/bin/tools/paledit/meson.build
index 6f74ac8ccc..3ea1a9795c 100644
--- a/src/bin/tools/paledit/meson.build
+++ b/src/bin/tools/paledit/meson.build
@@ -4,7 +4,8 @@ executable('enlightenment_paledit',
'colsel.c',
'palcols.c',
'palimg.c',
- 'palsel.c'
+ 'palsel.c',
+ 'undoredo.c'
],
include_directories: include_directories('.'),
dependencies : [ dep_elementary, deps ],
diff --git a/src/bin/tools/paledit/palcols.c b/src/bin/tools/paledit/palcols.c
index 5b2415380c..93bcf1e792 100644
--- a/src/bin/tools/paledit/palcols.c
+++ b/src/bin/tools/paledit/palcols.c
@@ -121,6 +121,7 @@ _pal_color_add(Evas_Object *win)
if (!strcmp(col->name, plain)) goto exists;
}
elm_colorselector_color_get(evas_object_data_get(win, "pal_colorsel"), &r, &g, &b, &a);
+ undoredo_op_col_add(win, plain, r, g, b, a);
elm_config_palette_color_set(pal, plain, r, g, b, a);
EINA_LIST_FOREACH(pal->colors, l, col)
{
@@ -157,6 +158,7 @@ _pal_color_del(Evas_Object *win)
{
Elm_Palette *pal = evas_object_data_get(win, "pal");
Elm_Palette_Color *col = elm_object_item_data_get(it);
+ undoredo_op_col_del(win, col->name, col->r, col->g, col->b, col->a);
if (col->name) elm_config_palette_color_unset(pal, col->name);
it_sel = elm_genlist_item_next_get(it);
if (!it_sel) it_sel = elm_genlist_item_prev_get(it);
@@ -491,6 +493,22 @@ _pal_hover_add(Evas_Object *win, Evas_Object *button)
}
static void
+_cb_undo_click(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *win = data;
+
+ underedo_undo(win);
+}
+
+static void
+_cb_redo_click(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *win = data;
+
+ underedo_redo(win);
+}
+
+static void
_cb_modify_click(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Evas_Object *win = data, *o;
@@ -550,6 +568,32 @@ palcols_add(Evas_Object *win)
evas_object_show(o);
evas_object_data_set(win, "pal_image", o);
+ btn = o = elm_button_add(win);
+ evas_object_size_hint_weight_set(o, 0.0, 0.0);
+ evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_smart_callback_add(o, "clicked", _cb_undo_click, win);
+ elm_box_pack_end(bxh, o);
+ evas_object_show(o);
+ elm_object_tooltip_text_set(o, "Undo");
+
+ o = elm_icon_add(win);
+ elm_icon_standard_set(o, "edit-undo");
+ elm_object_content_set(btn, o);
+ evas_object_show(o);
+
+ btn = o = elm_button_add(win);
+ evas_object_size_hint_weight_set(o, 0.0, 0.0);
+ evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_smart_callback_add(o, "clicked", _cb_redo_click, win);
+ elm_box_pack_end(bxh, o);
+ evas_object_show(o);
+ elm_object_tooltip_text_set(o, "Redo");
+
+ o = elm_icon_add(win);
+ elm_icon_standard_set(o, "edit-redo");
+ elm_object_content_set(btn, o);
+ evas_object_show(o);
+
o = elm_genlist_add(win);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
@@ -559,7 +603,6 @@ palcols_add(Evas_Object *win)
elm_object_tooltip_text_set(o, "Colors listed in this palette");
btn = o = elm_button_add(win);
- evas_object_size_hint_weight_set(o, 1.0, 0.0);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(o, "clicked", _cb_modify_click, win);
diff --git a/src/bin/tools/paledit/undoredo.c b/src/bin/tools/paledit/undoredo.c
new file mode 100644
index 0000000000..4ef1f5ed7c
--- /dev/null
+++ b/src/bin/tools/paledit/undoredo.c
@@ -0,0 +1,337 @@
+#include "main.h"
+
+typedef enum
+{
+ ENTRY_NONE,
+ ENTRY_CHANGE,
+ ENTRY_ADD,
+ ENTRY_DEL
+} Entry_Type;
+
+typedef struct
+{
+ double tim;
+ const char *name;
+ Entry_Type type;
+ unsigned char r, g, b, a;
+ unsigned char r2, g2, b2, a2;
+} Entry;
+
+static Eina_List *undo = NULL;
+static Eina_List *list = NULL;
+static int ignore = 0;
+
+/*
+static void
+_dump(void)
+{
+ Entry *en;
+ Eina_List *l;
+
+ printf("--------------------------------------------------\n");
+ EINA_LIST_FOREACH(list, l, en)
+ {
+ if (l == undo) printf("* ");
+ else printf(" ");
+ switch (en->type)
+ {
+ case ENTRY_NONE:
+ printf("UNDO: none\n");
+ break;
+ case ENTRY_CHANGE:
+ printf("UNDO: change %5.2f [%s] %3i %3i %3i %3i -> %3i %3i %3i %3i\n",
+ en->tim,
+ en->name,
+ en->r, en->g, en->b, en->a,
+ en->r2, en->g2, en->b2, en->a2
+ );
+ break;
+ case ENTRY_ADD:
+ printf("UNDO: add %5.2f [%s] %3i %3i %3i %3i\n",
+ en->tim,
+ en->name,
+ en->r, en->g, en->b, en->a
+ );
+ break;
+ case ENTRY_DEL:
+ printf("UNDO: del %5.2f [%s] %3i %3i %3i %3i\n",
+ en->tim,
+ en->name,
+ en->r, en->g, en->b, en->a
+ );
+ break;
+ default:
+ break;
+ }
+ }
+}
+*/
+
+static void
+_undo_init(void)
+{
+ Entry *en;
+
+ if (list) return;
+ en = calloc(1, sizeof(Entry));
+ if (!en) return;
+ en->name = eina_stringshare_add("");
+ en->tim = 0.0;
+ en->type = ENTRY_NONE;
+ list = eina_list_append(list, en);
+ undo = list;
+}
+
+static void
+_undo_remove(void)
+{
+ Entry *en;
+ Eina_List *l, *ll;
+
+ if (!undo) return;
+ EINA_LIST_REVERSE_FOREACH_SAFE(list, l, ll, en)
+ {
+ if (l == undo) break;
+ if (en->type == ENTRY_NONE) break;
+ eina_stringshare_del(en->name);
+ free(en);
+ list = eina_list_remove_list(list, l);
+ }
+ undo = NULL;
+}
+
+static void
+_undo_apply(Evas_Object *win, Entry *en)
+{
+ Elm_Palette *pal = evas_object_data_get(win, "pal");
+
+ ignore++;
+ switch (en->type)
+ {
+ case ENTRY_CHANGE:
+ elm_config_palette_color_set(pal, en->name,
+ en->r2, en->g2, en->b2, en->a2);
+ palcols_fill(win);
+ // XXX: update colorsel
+ break;
+ case ENTRY_ADD:
+ elm_config_palette_color_unset(pal, en->name);
+ palcols_fill(win);
+ break;
+ case ENTRY_DEL:
+ elm_config_palette_color_set(pal, en->name,
+ en->r, en->g, en->b, en->a);
+ palcols_fill(win);
+ break;
+ default:
+ break;
+ }
+ ignore--;
+}
+
+static void
+_redo_apply(Evas_Object *win, Entry *en)
+{
+ Elm_Palette *pal = evas_object_data_get(win, "pal");
+
+ ignore++;
+ switch (en->type)
+ {
+ case ENTRY_CHANGE:
+ elm_config_palette_color_set(pal, en->name,
+ en->r2, en->g2, en->b2, en->a2);
+ palcols_fill(win);
+ // XXX: update colorsel
+ break;
+ case ENTRY_ADD:
+ elm_config_palette_color_set(pal, en->name,
+ en->r, en->g, en->b, en->a);
+ palcols_fill(win);
+ break;
+ case ENTRY_DEL:
+ elm_config_palette_color_unset(pal, en->name);
+ palcols_fill(win);
+ break;
+ default:
+ break;
+ }
+ ignore--;
+}
+
+void
+undoredo_op_col_add(Evas_Object *win EINA_UNUSED,
+ const char *col,
+ int r, int g, int b, int a)
+{
+ Entry *en;
+ double t;
+
+ if (ignore) return;
+ if (!col) return;
+ t = ecore_time_get();
+ _undo_remove();
+ en = calloc(1, sizeof(Entry));
+ if (!en) return;
+ en->name = eina_stringshare_add(col);
+ en->tim = t;
+ en->type = ENTRY_ADD;
+ en->r = r;
+ en->g = g;
+ en->b = b;
+ en->a = a;
+ _undo_init();
+ list = eina_list_append(list, en);
+ undo = NULL;
+// _dump();
+}
+
+void
+undoredo_op_col_del(Evas_Object *win EINA_UNUSED,
+ const char *col,
+ int r, int g, int b, int a)
+{
+ Entry *en;
+ double t;
+
+ if (ignore) return;
+ if (!col) return;
+ t = ecore_time_get();
+ _undo_remove();
+ en = calloc(1, sizeof(Entry));
+ if (!en) return;
+ en->name = eina_stringshare_add(col);
+ en->tim = t;
+ en->type = ENTRY_DEL;
+ en->r = r;
+ en->g = g;
+ en->b = b;
+ en->a = a;
+ _undo_init();
+ list = eina_list_append(list, en);
+ undo = NULL;
+// _dump();
+}
+
+void
+undoredo_op_col_change(Evas_Object *win EINA_UNUSED,
+ const char *col,
+ int r_from, int g_from, int b_from, int a_from,
+ int r_to, int g_to, int b_to, int a_to)
+{
+ Entry *en, *en_last = NULL;
+ Eina_List *l;
+ double t;
+
+ if (ignore) return;
+ if (!col) return;
+ if ((r_from == r_to) && (g_from == g_to) &&
+ (b_from == b_to) && (a_from == a_to)) return;
+ t = ecore_time_get();
+ _undo_remove();
+ l = eina_list_last(list);
+ if (l)
+ {
+ en = l->data;
+ if ((en->type == ENTRY_CHANGE) &&
+ (!strcmp(col, en->name)) &&
+ ((t - en->tim) < 0.5))
+ {
+ en->tim = t;
+ en->r2 = r_to;
+ en->g2 = g_to;
+ en->b2 = b_to;
+ en->a2 = a_to;
+// _dump();
+ return;
+ }
+ }
+ EINA_LIST_REVERSE_FOREACH(list, l, en)
+ {
+ if (en->type == ENTRY_CHANGE)
+ {
+ if (!strcmp(en->name, col)) en_last = en;
+ }
+ else break;
+ }
+ _undo_init();
+ if (!en_last)
+ {
+ en = calloc(1, sizeof(Entry));
+ if (!en) return;
+ en->name = eina_stringshare_add(col);
+ en->tim = t - 1.0;
+ en->type = ENTRY_CHANGE;
+ en->r = r_from;
+ en->g = g_from;
+ en->b = b_from;
+ en->a = a_from;
+ en->r2 = r_from;
+ en->g2 = g_from;
+ en->b2 = b_from;
+ en->a2 = a_from;
+ list = eina_list_append(list, en);
+ }
+ en = calloc(1, sizeof(Entry));
+ if (!en) return;
+ en->name = eina_stringshare_add(col);
+ en->tim = t;
+ en->type = ENTRY_CHANGE;
+ en->r = r_from;
+ en->g = g_from;
+ en->b = b_from;
+ en->a = a_from;
+ en->r2 = r_to;
+ en->g2 = g_to;
+ en->b2 = b_to;
+ en->a2 = a_to;
+ _undo_init();
+ list = eina_list_append(list, en);
+ undo = NULL;
+// _dump();
+}
+
+void
+undoredo_reset(Evas_Object *win EINA_UNUSED)
+{
+ Entry *en;
+
+ EINA_LIST_FREE(list, en)
+ {
+ eina_stringshare_del(en->name);
+ free(en);
+ }
+ undo = NULL;
+}
+
+void
+underedo_undo(Evas_Object *win)
+{
+ Entry *en;
+
+ if (undo)
+ {
+ en = undo->data;
+ if (en->type == ENTRY_NONE) return;
+ undo = undo->prev;
+ }
+ else undo = eina_list_last(list);
+ if (!undo) return;
+
+ en = undo->data;
+ if (en->type == ENTRY_NONE) return;
+ _undo_apply(win, en);
+// _dump();
+}
+
+void
+underedo_redo(Evas_Object *win)
+{
+ Entry *en;
+
+ if (!undo) return;
+ undo = undo->next;
+ if (!undo) return;
+ en = undo->data;
+ _redo_apply(win, en);
+// _dump();
+}