elm_code: add support for redo

Summary:
now, elm_code support redo.
shortcut is <Ctrl> + <y>

Test Plan:
1. elementary_test - Code Editor
2. Check that undo and redo are work correctly.

Reviewers: ajwillia.ms

Reviewed By: ajwillia.ms

Subscribers: cedric, jpeg

Differential Revision: https://phab.enlightenment.org/D4642
This commit is contained in:
YeongJong Lee 2017-02-02 18:07:02 +00:00 committed by Andy Williams
parent 1b53925b4c
commit 4aee312774
3 changed files with 81 additions and 25 deletions

View File

@ -1249,7 +1249,7 @@ _elm_code_widget_change_selection_add(Evas_Object *widget)
change = _elm_code_widget_change_create(selection->start_col,
selection->start_line,
selection->end_col + 1,
selection->end_col,
selection->end_line,
selection_text,
strlen(selection_text),
@ -1360,8 +1360,8 @@ _elm_code_widget_newline(Elm_Code_Widget *widget)
Elm_Code *code;
Elm_Code_Line *line;
Elm_Code_Widget_Change_Info *change;
unsigned int row, col, position, oldlen, width, indent;
char *oldtext, *leading;
unsigned int row, col, position, oldlen, width, indent, textlen;
char *oldtext, *leading, *text;
_elm_code_widget_change_selection_add(widget);
elm_code_widget_selection_delete(widget);
@ -1394,9 +1394,14 @@ _elm_code_widget_newline(Elm_Code_Widget *widget)
efl_event_callback_legacy_call(widget, ELM_OBJ_CODE_WIDGET_EVENT_CHANGED_USER, NULL);
free(leading);
change = _elm_code_widget_change_create(width + 1, row, indent - 1, row + 1, "\n", 1, EINA_TRUE);
textlen = strlen(leading) + 2;
text = malloc(sizeof(char) * textlen);
snprintf(text, textlen, "\n%s", leading);
change = _elm_code_widget_change_create(width + 1, row, indent - 1, row + 1, text, strlen(text), EINA_TRUE);
_elm_code_widget_undo_change_add(widget, change);
_elm_code_widget_change_free(change);
free(text);
}
static void
@ -1479,7 +1484,7 @@ _elm_code_widget_backspace(Elm_Code_Widget *widget)
efl_event_callback_legacy_call(widget, ELM_OBJ_CODE_WIDGET_EVENT_CHANGED_USER, NULL);
change = _elm_code_widget_change_create(start_col, row, end_col, row, text, char_width, EINA_FALSE);
change = _elm_code_widget_change_create(start_col, row, end_col - 1, row, text, char_width, EINA_FALSE);
_elm_code_widget_undo_change_add(widget, change);
_elm_code_widget_change_free(change);
}
@ -1524,7 +1529,7 @@ _elm_code_widget_delete(Elm_Code_Widget *widget)
elm_obj_code_widget_cursor_position_set(widget, row, start_col);
efl_event_callback_legacy_call(widget, ELM_OBJ_CODE_WIDGET_EVENT_CHANGED_USER, NULL);
change = _elm_code_widget_change_create(start_col, row, col, row, text, char_width, EINA_FALSE);
change = _elm_code_widget_change_create(start_col, row, col - 1, row, text, char_width, EINA_FALSE);
_elm_code_widget_undo_change_add(widget, change);
_elm_code_widget_change_free(change);
}
@ -1545,6 +1550,8 @@ _elm_code_widget_control_key_down_cb(Elm_Code_Widget *widget, const char *key)
elm_code_widget_selection_paste(widget);
else if (!strcmp("x", key))
elm_code_widget_selection_cut(widget);
else if (!strcmp("y", key))
elm_code_widget_redo(widget);
else if (!strcmp("z", key))
elm_code_widget_undo(widget);
}

View File

@ -275,6 +275,9 @@ class Elm.Code_Widget (Elm.Layout, Elm.Interface.Atspi.Text)
undo {
[[Undo last action]]
}
redo {
[[Redo last action]]
}
}
implements {
class.constructor;

View File

@ -6,6 +6,25 @@
#include "elm_code_widget_private.h"
static void
_elm_code_widget_undo_prev_clear(Evas_Object *widget)
{
Elm_Code_Widget_Data *pd;
Elm_Code_Widget_Change_Info *info;
Eina_List *list;
pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
if (!pd->undo_stack_ptr)
return;
for (list = eina_list_prev(pd->undo_stack_ptr); list; list = eina_list_prev(list))
{
info = eina_list_data_get(list);
free(info->content);
free(info);
}
}
Elm_Code_Widget_Change_Info *
_elm_code_widget_undo_info_copy(Elm_Code_Widget_Change_Info *info)
{
@ -13,8 +32,7 @@ _elm_code_widget_undo_info_copy(Elm_Code_Widget_Change_Info *info)
copy = calloc(1, sizeof(*info));
memcpy(copy, info, sizeof(*info));
copy->content = malloc(sizeof(char) * (info->length + 1));
strncpy(copy->content, info->content, info->length);
copy->content = strndup(info->content, info->length);
return copy;
}
@ -29,6 +47,8 @@ _elm_code_widget_undo_change_add(Evas_Object *widget,
info_copy = _elm_code_widget_undo_info_copy(info);
pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
_elm_code_widget_undo_prev_clear(widget);
pd->undo_stack_ptr = eina_list_prepend(pd->undo_stack_ptr, info_copy);
pd->undo_stack = pd->undo_stack_ptr;
}
@ -38,8 +58,9 @@ _elm_code_widget_undo_change(Evas_Object *widget,
Elm_Code_Widget_Change_Info *info)
{
Elm_Code_Widget_Data *pd;
unsigned int textlen, position, row, col;
unsigned int textlen, position, row, col, newrow, remainlen;
short nllen;
char *content;
Elm_Code_Line *line;
pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
@ -51,37 +72,40 @@ _elm_code_widget_undo_change(Evas_Object *widget,
}
else
{
newrow = info->start_line;
content = info->content;
remainlen = info->length;
elm_code_widget_selection_clear(widget);
elm_code_widget_cursor_position_set(widget, info->start_line, info->start_col);
unsigned int newrow = info->start_line;
elm_code_widget_cursor_position_set(widget, info->start_line,
info->start_col);
while (newrow <= info->end_line)
{
line = elm_code_file_line_get(pd->code->file, newrow);
if (newrow != info->end_line)
{
textlen = info->length;
textlen = elm_code_text_newlinenpos(info->content, info->length, &nllen);
info->length -= textlen + nllen;
textlen = remainlen;
textlen = elm_code_text_newlinenpos(content, remainlen,
&nllen);
remainlen -= textlen + nllen;
_elm_code_widget_text_at_cursor_insert_no_undo(widget,
info->content,
content,
textlen);
elm_obj_code_widget_cursor_position_get(widget, &row, &col);
position = elm_code_widget_line_text_position_for_column_get(widget, line, col);
elm_code_line_split_at(line, position);
elm_code_widget_cursor_position_set(widget, newrow + 1, 1);
info->content += textlen + nllen;
content += textlen + nllen;
}
else
{
_elm_code_widget_text_at_cursor_insert_no_undo(widget,
info->content,
info->length);
content,
strlen(content));
}
newrow++;
}
if (info->end_col < 1)
info->end_col = 1;
elm_code_widget_cursor_position_set(widget, info->end_line, info->end_col);
elm_code_widget_cursor_position_set(widget, info->end_line,
info->end_col + 1);
}
}
@ -96,9 +120,31 @@ _elm_code_widget_undo(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd)
info = eina_list_data_get(pd->undo_stack_ptr);
_elm_code_widget_undo_change(obj, info);
if (eina_list_next(pd->undo_stack_ptr))
pd->undo_stack_ptr = eina_list_next(pd->undo_stack_ptr);
else
pd->undo_stack_ptr = NULL;
pd->undo_stack_ptr = eina_list_next(pd->undo_stack_ptr);
}
static void
_elm_code_widget_redo(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd)
{
Elm_Code_Widget_Change_Info *info, *redo_info;
Eina_List *redo_ptr;
if (pd->undo_stack_ptr)
redo_ptr = eina_list_prev(pd->undo_stack_ptr);
else
redo_ptr = eina_list_last(pd->undo_stack);
if (!redo_ptr)
return;
info = eina_list_data_get(redo_ptr);
redo_info = _elm_code_widget_undo_info_copy(info);
redo_info->insert = redo_info->insert ? EINA_FALSE : EINA_TRUE;
_elm_code_widget_undo_change(obj, redo_info);
pd->undo_stack_ptr = redo_ptr;
free(redo_info->content);
free(redo_info);
}