From 6aea530622577b3686a7066a1d99422d2f713681 Mon Sep 17 00:00:00 2001 From: Mykyta Biliavskyi Date: Thu, 10 Dec 2015 10:53:12 +0900 Subject: [PATCH] Text settings: Add analysis typed text for redoundo feature. Added cases: Analyse auto indention for new lines. It mean, that redo/undo line creation will finished by one step. Analyse input symbols speed. In case when user writes somethenigi and takes a short delay (by default 0.8sec) between written symbols - redo/undo action will use this delay as point to create new node in redo/undo queue. Analyse input symbols on a "words". Ongoing alphabetic symbols between nonalphabetic symbols known as "word". Redo/undo action will use for a step a whole "word". In text setting added addition toggle named "Smart undo/redo". By default this feature is disabled. Todo: make this feature work with auto intendation. Prortotype here: https://phab.enlightenment.org/D1288 --- src/bin/config_data.c | 18 ++++++++++ src/bin/main.c | 1 + src/bin/text_setting.c | 15 +++++++- src/include/config_data.h | 2 ++ src/include/text_setting.h | 2 ++ src/lib/edc_editor.c | 16 +++++++++ src/lib/enventor_object.eo | 9 +++++ src/lib/enventor_private.h | 3 ++ src/lib/enventor_smart.c | 13 +++++++ src/lib/redoundo.c | 74 +++++++++++++++++++++++++++++++++++++- 10 files changed, 151 insertions(+), 2 deletions(-) diff --git a/src/bin/config_data.c b/src/bin/config_data.c index 3205b27..15327a9 100644 --- a/src/bin/config_data.c +++ b/src/bin/config_data.c @@ -38,6 +38,7 @@ typedef struct config_s Eina_Bool console; Eina_Bool auto_complete; Eina_Bool view_size_configurable; + Eina_Bool smart_undo_redo; } config_data; static config_data *g_cd = NULL; @@ -178,6 +179,7 @@ config_load(void) cd->auto_complete = EINA_TRUE; cd->view_size_configurable = EINA_FALSE; cd->version = ENVENTOR_CONFIG_VERSION; + cd->smart_undo_redo = EINA_FALSE; } g_cd = cd; @@ -282,6 +284,8 @@ eddc_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, config_data, "view_size_configurable", view_size_configurable, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, config_data, "smart_undo_redo", + smart_undo_redo, EET_T_UCHAR); } void @@ -732,6 +736,20 @@ config_font_scale_get(void) return cd->font_scale; } +Eina_Bool +config_smart_undo_redo_get(void) +{ + config_data *cd = g_cd; + return cd->smart_undo_redo; +} + +void +config_smart_undo_redo_set(Eina_Bool smart_undo_redo) +{ + config_data *cd = g_cd; + cd->smart_undo_redo = smart_undo_redo; +} + void config_auto_complete_set(Eina_Bool auto_complete) { diff --git a/src/bin/main.c b/src/bin/main.c index 3e05691..be0ed0e 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -56,6 +56,7 @@ enventor_common_setup(Evas_Object *enventor) enventor_object_live_view_scale_set(enventor, config_view_scale_get()); enventor_object_auto_indent_set(enventor, config_auto_indent_get()); enventor_object_auto_complete_set(enventor, config_auto_complete_get()); + enventor_object_smart_undo_redo_set(enventor, config_smart_undo_redo_get()); Eina_List *list = eina_list_append(NULL, config_output_path_get()); enventor_object_path_set(enventor, ENVENTOR_PATH_TYPE_EDJ, list); diff --git a/src/bin/text_setting.c b/src/bin/text_setting.c index 111916a..9292b13 100644 --- a/src/bin/text_setting.c +++ b/src/bin/text_setting.c @@ -864,6 +864,11 @@ text_setting_layout_create(Evas_Object *parent) config_auto_complete_get()); elm_box_pack_end(box, toggle_autocomp); + //Toggle (Smart Undo/Redo) + Evas_Object *toggle_smart_undo_redo = toggle_create(box, _("Smart Undo/Redo"), + config_smart_undo_redo_get()); + elm_box_pack_end(box, toggle_smart_undo_redo); + //Font Name and Style (Box) box = elm_box_add(layout); elm_box_horizontal_set(box, EINA_TRUE); @@ -953,7 +958,7 @@ text_setting_layout_create(Evas_Object *parent) tsd->toggle_linenum = toggle_linenum; tsd->toggle_indent = toggle_indent; tsd->toggle_autocomp = toggle_autocomp; - + tsd->toggle_smart_undo_redo = toggle_smart_undo_redo; return layout; } @@ -999,6 +1004,7 @@ text_setting_config_set(void) config_linenumber_set(elm_check_state_get(tsd->toggle_linenum)); config_auto_indent_set(elm_check_state_get(tsd->toggle_indent)); config_auto_complete_set(elm_check_state_get(tsd->toggle_autocomp)); + config_smart_undo_redo_set(elm_check_state_get(tsd->toggle_smart_undo_redo)); } static void @@ -1058,6 +1064,13 @@ text_setting_auto_complete_set(Eina_Bool enabled) elm_check_state_set(tsd->toggle_autocomp, enabled); } +void +text_setting_smart_undo_redo_set(Eina_Bool enabled) +{ + text_setting_data *tsd = g_tsd; + elm_check_state_set(tsd->toggle_smart_undo_redo, enabled); +} + void text_setting_init(void) { diff --git a/src/include/config_data.h b/src/include/config_data.h index 4b5771d..a1296da 100644 --- a/src/include/config_data.h +++ b/src/include/config_data.h @@ -58,3 +58,5 @@ double config_editor_size_get(void); void config_console_set(Eina_Bool enabled); void config_win_size_get(Evas_Coord *w, Evas_Coord *h); void config_win_size_set(Evas_Coord w, Evas_Coord h); +void config_smart_undo_redo_set(Eina_Bool smart_undo_redo); +Eina_Bool config_smart_undo_redo_get(void); diff --git a/src/include/text_setting.h b/src/include/text_setting.h index 5e37be2..55a1306 100644 --- a/src/include/text_setting.h +++ b/src/include/text_setting.h @@ -15,6 +15,7 @@ struct text_setting_s Evas_Object *toggle_linenum; Evas_Object *toggle_indent; Evas_Object *toggle_autocomp; + Evas_Object *toggle_smart_undo_redo; color_keyword *color_keyword_list; char *syntax_template_format; @@ -37,5 +38,6 @@ void text_setting_font_scale_set(double font_scale); void text_setting_linenumber_set(Eina_Bool enabled); void text_setting_auto_indent_set(Eina_Bool enabled); void text_setting_auto_complete_set(Eina_Bool enabled); +void text_setting_smart_undo_redo_set(Eina_Bool enabled); void text_setting_term(void); void text_setting_init(void); diff --git a/src/lib/edc_editor.c b/src/lib/edc_editor.c index 66cfb33..bea9119 100644 --- a/src/lib/edc_editor.c +++ b/src/lib/edc_editor.c @@ -60,6 +60,7 @@ struct editor_s Eina_Bool part_highlight : 1; Eina_Bool ctxpopup_enabled : 1; Eina_Bool on_save : 1; + Eina_Bool smart_undo_redo : 1; }; /*****************************************************************************/ @@ -1184,6 +1185,7 @@ edit_init(Evas_Object *enventor) ed->auto_indent = EINA_TRUE; ed->part_highlight = EINA_TRUE; ed->ctxpopup_enabled = EINA_TRUE; + ed->smart_undo_redo = EINA_FALSE; ed->cur_line = -1; ed->select_pos = -1; ed->font_scale = 1; @@ -1432,6 +1434,20 @@ edit_disabled_set(edit_data *ed, Eina_Bool disabled) else if (ed->part_highlight) edit_view_sync(ed); } +void +edit_smart_undo_redo_set(edit_data *ed, Eina_Bool smart_undo_redo) +{ + smart_undo_redo = !!smart_undo_redo; + ed->smart_undo_redo = smart_undo_redo; + redoundo_smart_set(ed->rd, smart_undo_redo); +} + +Eina_Bool +edit_smart_undo_redo_get(edit_data *ed) +{ + return ed->smart_undo_redo; +} + void edit_auto_indent_set(edit_data *ed, Eina_Bool auto_indent) { diff --git a/src/lib/enventor_object.eo b/src/lib/enventor_object.eo index a837f0e..7b3fb46 100644 --- a/src/lib/enventor_object.eo +++ b/src/lib/enventor_object.eo @@ -91,6 +91,15 @@ class Enventor.Object (Elm.Widget, Efl.File) { linenumber: bool; } } + @property smart_undo_redo { + set { + } + get { + } + values { + smart_undo_redo: bool; + } + } path_set { return: Eina_Bool; params { diff --git a/src/lib/enventor_private.h b/src/lib/enventor_private.h index 8347dc7..3e2adc6 100644 --- a/src/lib/enventor_private.h +++ b/src/lib/enventor_private.h @@ -195,6 +195,7 @@ void redoundo_entry_region_push(redoundo_data *rd, int cursor_pos, int cursor_po int redoundo_undo(redoundo_data *rd, Eina_Bool *changed); int redoundo_redo(redoundo_data *rd, Eina_Bool *changed); void redoundo_n_diff_cancel(redoundo_data *rd, unsigned int n); +void redoundo_smart_set(redoundo_data *rd, Eina_Bool status); /* edj_viewer */ @@ -271,6 +272,8 @@ Eina_Bool edit_part_highlight_get(edit_data *ed); void edit_ctxpopup_enabled_set(edit_data *ed, Eina_Bool enabled); Eina_Bool edit_ctxpopup_enabled_get(edit_data *ed); Eina_Bool edit_ctxpopup_visible_get(edit_data *ed); +void edit_smart_undo_redo_set(edit_data *ed, Eina_Bool smart_undo_redo); +Eina_Bool edit_smart_undo_redo_get(edit_data *ed); void edit_ctxpopup_dismiss(edit_data *ed); Eina_Bool edit_load(edit_data *ed, const char *edc_path); void edit_selection_clear(edit_data *ed); diff --git a/src/lib/enventor_smart.c b/src/lib/enventor_smart.c index 8d64804..e99fab0 100644 --- a/src/lib/enventor_smart.c +++ b/src/lib/enventor_smart.c @@ -309,6 +309,19 @@ _enventor_object_linenumber_get(Eo *obj EINA_UNUSED, Enventor_Object_Data *pd) return edit_linenumber_get(pd->ed); } +EOLIAN static void +_enventor_object_smart_undo_redo_set(Eo *obj EINA_UNUSED, Enventor_Object_Data *pd, + Eina_Bool smart_undo_redo) +{ + edit_smart_undo_redo_set(pd->ed, smart_undo_redo); +} + +EOLIAN static Eina_Bool +_enventor_object_smart_undo_redo_get(Eo *obj EINA_UNUSED, Enventor_Object_Data *pd) +{ + return edit_smart_undo_redo_get(pd->ed); +} + EOLIAN static void _enventor_object_auto_indent_set(Eo *obj EINA_UNUSED, Enventor_Object_Data *pd, Eina_Bool auto_indent) diff --git a/src/lib/redoundo.c b/src/lib/redoundo.c index 819d951..01d7106 100644 --- a/src/lib/redoundo.c +++ b/src/lib/redoundo.c @@ -6,6 +6,7 @@ #include "enventor_private.h" #define DEFAULT_QUEUE_SIZE 200 +#define INPUT_SPEED 0.8 //how much time need to input one symbol with speed 75sym/min typedef struct diff_s { @@ -26,11 +27,72 @@ struct redoundo_s diff_data *last_diff; unsigned int queue_max; //Maximum queuing data count 0: unlimited Eina_Bool internal_change : 1; //Entry change by redoundo + struct { + Eina_Bool enable; + Ecore_Timer *timer; + Eina_Bool continues_input; + double input_delay; + } smart; }; /*****************************************************************************/ /* Internal method implementation */ /*****************************************************************************/ +Eina_Bool +_input_timer_cb(void *data) +{ + redoundo_data *rd = (redoundo_data *)data; + if (!rd->smart.continues_input) return ECORE_CALLBACK_CANCEL; + rd->smart.continues_input = EINA_FALSE; + ecore_timer_del(rd->smart.timer); + rd->smart.timer = NULL; + return ECORE_CALLBACK_CANCEL; +} + +static diff_data * +smart_analyser(redoundo_data *rd, diff_data *diff) +{ + if (!rd->smart.enable) return diff; + + if (rd->smart.timer) + { + ecore_timer_del(rd->smart.timer); + rd->smart.timer = NULL; + } + + if ((!diff) || (diff->length > 1) || (!rd->last_diff)) return diff; + + /* Autoindent. Here need edit_data pointer, + * for check status of autoindent feature. + * + * if (edit_auto_indent_get(edit_obj_get)) + * { + * if (strstr(diff->text, "
")) diff->relative = EINA_TRUE; + * else diff->relative = EINA_FALSE; + * } + */ + + // Analyse speed of text input and words separates + if ((rd->smart.continues_input) && (!diff->relative) && + (isalpha(diff->text[0])) && (isalpha(rd->last_diff->text[0]))) + { + diff_data *tmp = diff; + const char *text; + diff = rd->last_diff; + diff->length += tmp->length; + text = eina_stringshare_printf("%s%s", diff->text, tmp->text); + eina_stringshare_replace(&diff->text, text); + eina_stringshare_del(text); + rd->last_diff = eina_list_data_get(eina_list_prev(rd->current_node)); + rd->queue = eina_list_remove_list(rd->queue, rd->current_node); + eina_stringshare_del(tmp->text); + free(tmp); + } + + rd->smart.continues_input = EINA_TRUE; + rd->smart.timer = ecore_timer_add(rd->smart.input_delay, _input_timer_cb, rd); + return diff; +} static void untracked_diff_free(redoundo_data *rd) @@ -104,7 +166,7 @@ entry_changed_user_cb(void *data, Evas_Object *obj EINA_UNUSED, diff->length = abs(length); diff->action = EINA_FALSE; } - diff->relative = EINA_FALSE; + diff = smart_analyser(rd, diff); untracked_diff_free(rd); rd->queue = eina_list_append(rd->queue, diff); @@ -319,6 +381,8 @@ redoundo_init(Evas_Object *entry) rd->textblock = elm_entry_textblock_get(entry); rd->cursor = evas_object_textblock_cursor_new(rd->textblock); rd->queue_max = DEFAULT_QUEUE_SIZE; + rd->smart.enable = EINA_FALSE; + rd->smart.input_delay = INPUT_SPEED; //FIXME: Why signal callback? not smart callback? elm_object_signal_callback_add(entry, "entry,changed,user", "*", @@ -337,6 +401,7 @@ redoundo_clear(redoundo_data *rd) free(data); } rd->internal_change = EINA_FALSE; + ecore_timer_del(rd->smart.timer); } void @@ -395,3 +460,10 @@ redoundo_n_diff_cancel(redoundo_data *rd, unsigned int n) rd->last_diff = (diff_data *)eina_list_data_get(rd->current_node); untracked_diff_free(rd); } + +void +redoundo_smart_set(redoundo_data *rd, Eina_Bool status) +{ + if (!rd) return; + rd->smart.enable = status; +}