From ad379ce04fa3dae4ef06c5f6211bc4b962cb3fa4 Mon Sep 17 00:00:00 2001 From: Alastair Poole Date: Fri, 27 Jul 2018 15:20:24 +0100 Subject: [PATCH] elm_code_widget: fix keyboard and scrolling with active selection. Summary: This adds some attributes to the selectiont type in elm_code. Including the type (whether it is mouse or keyboard) and also whether a selection is in progress. Thus we can reliably select around the file and also move/scroll when there is an active selection. Test Plan: Drag and select text with mouse. Also the same with keyboard (hold shift and select). Leave selection active and scroll around the file. The selection should remain and full movement is possible while retaining the active selection. This could really be refactored for a next major release. Reviewers: #committers, ajwillia.ms, cedric Reviewed By: ajwillia.ms Subscribers: zmike Tags: #efl Differential Revision: https://phab.enlightenment.org/D6676 --- src/lib/elementary/elm_code_widget.c | 27 ++++++++++++++++- src/lib/elementary/elm_code_widget_private.h | 12 ++++++++ .../elementary/elm_code_widget_selection.c | 29 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/lib/elementary/elm_code_widget.c b/src/lib/elementary/elm_code_widget.c index 36e7ccfdf0..5157838667 100644 --- a/src/lib/elementary/elm_code_widget.c +++ b/src/lib/elementary/elm_code_widget.c @@ -344,6 +344,16 @@ _elm_code_widget_fill_cursor(Elm_Code_Widget *widget, unsigned int number, int g if (pd->cursor_col + gutter - 1 >= (unsigned int) w) return; + if (pd->selection && !pd->selection->in_progress) + { + Elm_Code_Line *line = elm_code_file_line_get(pd->code->file, number); + if (!line) + return; + + if (!elm_code_widget_line_visible_get(widget, line)) + return; + } + _elm_code_widget_cursor_update(widget, pd); } } @@ -451,6 +461,9 @@ _elm_code_widget_cursor_selection_set(Elm_Code_Widget *widget, Elm_Code_Widget_D end_line = pd->selection->end_line; end_col = pd->selection->end_col; + if (pd->selection->type == ELM_CODE_WIDGET_SELECTION_KEYBOARD) + return; + if ((pd->selection->start_line == pd->selection->end_line && pd->selection->end_col > pd->selection->start_col) || (pd->selection->start_line < pd->selection->end_line)) { @@ -700,7 +713,8 @@ _elm_code_widget_cursor_move(Elm_Code_Widget *widget, Elm_Code_Widget_Data *pd, pd->cursor_col = elm_code_widget_line_text_column_width_to_position(widget, line_obj, position); efl_event_callback_legacy_call(widget, ELM_OBJ_CODE_WIDGET_EVENT_CURSOR_CHANGED, widget); - _elm_code_widget_cursor_ensure_visible(widget); + if (!pd->selection || (pd->selection && pd->selection->in_progress)) + _elm_code_widget_cursor_ensure_visible(widget); if (oldrow != pd->cursor_line) _elm_code_widget_refresh(widget, line_obj); @@ -1158,6 +1172,11 @@ _elm_code_widget_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj if (!pd->selection) if (col > 0 && row <= elm_code_file_lines_get(pd->code->file)) elm_code_widget_selection_start(widget, row, col); + + _elm_code_widget_selection_type_set(widget, ELM_CODE_WIDGET_SELECTION_MOUSE); + _elm_code_widget_selection_in_progress_set(widget, EINA_TRUE); + + elm_code_widget_selection_end(widget, row, col); } @@ -1179,6 +1198,8 @@ _elm_code_widget_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj E if (pd->selection) { + _elm_code_widget_selection_in_progress_set(widget, EINA_FALSE); + if (pd->selection->start_line == pd->selection->end_line && pd->selection->start_col == pd->selection->end_col) elm_code_widget_selection_clear(widget); @@ -1736,6 +1757,9 @@ _elm_code_widget_key_down_cb(void *data, Evas *evas EINA_UNUSED, if (!pd->selection) elm_code_widget_selection_start(widget, pd->cursor_line, pd->cursor_col - (backwards?1:0)); + _elm_code_widget_selection_type_set(widget, ELM_CODE_WIDGET_SELECTION_KEYBOARD); + _elm_code_widget_selection_in_progress_set(widget, EINA_TRUE); + if (pd->selection && pd->selection->start_line == pd->selection->end_line) { if ((pd->selection->end_col == pd->selection->start_col && !backwards) || @@ -1776,6 +1800,7 @@ _elm_code_widget_key_down_cb(void *data, Evas *evas EINA_UNUSED, adjust = (pd->selection->end_line > pd->selection->start_line); elm_code_widget_selection_end(widget, pd->cursor_line, pd->cursor_col - (adjust?1:0)); + _elm_code_widget_selection_in_progress_set(widget, EINA_FALSE); } } diff --git a/src/lib/elementary/elm_code_widget_private.h b/src/lib/elementary/elm_code_widget_private.h index 21d652d97d..ec1e53dc35 100644 --- a/src/lib/elementary/elm_code_widget_private.h +++ b/src/lib/elementary/elm_code_widget_private.h @@ -4,10 +4,18 @@ /** * Structure holding the info about a selected region. */ +typedef enum +{ + ELM_CODE_WIDGET_SELECTION_KEYBOARD, + ELM_CODE_WIDGET_SELECTION_MOUSE, +} Elm_Code_Widget_Selection_Type; + typedef struct { unsigned int start_line, end_line; unsigned int start_col, end_col; + Elm_Code_Widget_Selection_Type type; + Eina_Bool in_progress; } Elm_Code_Widget_Selection_Data; typedef struct @@ -68,4 +76,8 @@ void _elm_code_widget_undo_change_add(Evas_Object *widget, Elm_Code_Widget_Chang void _elm_code_widget_change_selection_add(Evas_Object *widget); +void _elm_code_widget_selection_in_progress_set(Evas_Object *widget, Eina_Bool state); + +void _elm_code_widget_selection_type_set(Evas_Object *widget, Elm_Code_Widget_Selection_Type type); + #endif diff --git a/src/lib/elementary/elm_code_widget_selection.c b/src/lib/elementary/elm_code_widget_selection.c index 7111c42996..834c025e94 100644 --- a/src/lib/elementary/elm_code_widget_selection.c +++ b/src/lib/elementary/elm_code_widget_selection.c @@ -58,6 +58,8 @@ elm_code_widget_selection_start(Evas_Object *widget, pd->selection = selection; } + _elm_code_widget_selection_in_progress_set(widget, EINA_TRUE); + pd->selection->start_line = line; pd->selection->start_col = col; efl_event_callback_legacy_call(widget, ELM_OBJ_CODE_WIDGET_EVENT_SELECTION_START, widget); @@ -464,3 +466,30 @@ elm_code_widget_selection_is_empty(Evas_Object *widget) return ret; } + +void +_elm_code_widget_selection_in_progress_set(Evas_Object *widget, Eina_Bool state) +{ + Elm_Code_Widget_Data *pd; + + pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); + + if (!pd || !pd->selection) + return; + + pd->selection->in_progress = state; +} + +void +_elm_code_widget_selection_type_set(Evas_Object *widget, Elm_Code_Widget_Selection_Type type) +{ + Elm_Code_Widget_Data *pd; + + pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); + + if (!pd || !pd->selection) + return; + + pd->selection->type = type; +} +