diff options
author | Daniel Hirt <daniel.hirt@samsung.com> | 2016-06-13 10:59:59 +0000 |
---|---|---|
committer | Daniel Hirt <daniel.hirt@samsung.com> | 2016-06-13 14:47:47 +0000 |
commit | 6a33d922fbfe9db1b4a3c6198c0f0da706b63270 (patch) | |
tree | 90da7160da31ba07647089884d9bc30d08b44112 | |
parent | 38d1f9e140f5c042b2d76dc02bee821e8cd36a2f (diff) | |
download | efl-6a33d922fbfe9db1b4a3c6198c0f0da706b63270.tar.gz |
Efl.Ui.Text: implement selection logic (WIP)
-rw-r--r-- | src/lib/elementary/efl_ui_text.c | 247 |
1 files changed, 180 insertions, 67 deletions
diff --git a/src/lib/elementary/efl_ui_text.c b/src/lib/elementary/efl_ui_text.c index 2bbefb6309..d6914c6ccc 100644 --- a/src/lib/elementary/efl_ui_text.c +++ b/src/lib/elementary/efl_ui_text.c @@ -21,10 +21,12 @@ #include "elm_widget_entry.h" #include "efl_ui_text.eo.h" +typedef struct _Efl_Ui_Text_Data Efl_Ui_Text_Data; +typedef struct _Efl_Ui_Text_Rectangle Efl_Ui_Text_Rectangle; + /** * Base widget smart data extended with entry instance data. */ -typedef struct _Efl_Ui_Text_Data Efl_Ui_Text_Data; struct _Efl_Ui_Text_Data { Evas_Object *hit_rect, *entry_edje, *scr_edje; @@ -66,7 +68,8 @@ struct _Efl_Ui_Text_Data Elm_Input_Panel_Lang input_panel_lang; Elm_Input_Panel_Return_Key_Type input_panel_return_key_type; Elm_Input_Hints input_hints; - Edje_Cursor sel_handler_cursor; + Eo *sel_handler_cursor; + Eina_List *rects; void *input_panel_imdata; int input_panel_imdata_len; int input_panel_layout_variation; @@ -140,6 +143,12 @@ struct _Efl_Ui_Text_Data if (EINA_UNLIKELY(!eo_isa((obj), EFL_UI_TEXT_CLASS))) \ return +struct _Efl_Ui_Text_Rectangle +{ + Eina_Rectangle rect; + Evas_Object *obj_bg, *obj; +}; + #define MY_CLASS EFL_UI_TEXT_CLASS #define MY_CLASS_NAME "Efl_Ui_Text" @@ -218,10 +227,11 @@ struct _Mod_Api static void _create_selection_handlers(Evas_Object *obj, Efl_Ui_Text_Data *sd); static void _magnifier_move(void *data); -static void _update_decorations(Efl_Ui_Text_Data *sd); +static void _update_decorations(Eo *obj, Eo *text_obj); static void _create_text_cursors(Eo *obj, Efl_Ui_Text_Data *sd); static Eina_Bool _efl_ui_text_changed_cb(void *data EINA_UNUSED, const Eo_Event *event); -static Eina_Bool _text_cursor_changed_cb(void *data EINA_UNUSED, const Eo_Event *event); +static Eina_Bool _efl_ui_text_selection_changed_cb(void *data EINA_UNUSED, const Eo_Event *event); +static Eina_Bool _efl_ui_text_cursor_changed_cb(void *data EINA_UNUSED, const Eo_Event *event); static Mod_Api * _module_find(Evas_Object *obj EINA_UNUSED) @@ -1211,7 +1221,7 @@ _deferred_recalc_job(void *data) elm_widget_show_region_set(data, cx, cy, cw, ch, EINA_FALSE); } } - _update_decorations(sd); + _update_decorations(data, sw); } EOLIAN static void @@ -3612,28 +3622,32 @@ _start_handler_mouse_down_cb(void *data, EFL_UI_TEXT_DATA_GET(data, sd); Evas_Event_Mouse_Down *ev = event_info; - int start_pos, end_pos, main_pos, pos; + int start_pos, end_pos, pos; + Efl_Canvas_Text_Cursor *sel_start, *sel_end; + Efl_Canvas_Text_Cursor *main_cur; + + Eo *text_obj = edje_object_part_swallow_get(sd->entry_edje, "elm.text"); sd->start_handler_down = EINA_TRUE; - start_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - EDJE_CURSOR_SELECTION_BEGIN); - end_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - EDJE_CURSOR_SELECTION_END); - main_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - EDJE_CURSOR_MAIN); + + /* Get the cursors */ + efl_ui_text_interactive_selection_cursors_get(text_obj, &sel_start, &sel_end); + main_cur = efl_canvas_text_cursor_get(text_obj); + + start_pos = efl_canvas_text_cursor_position_get(sel_start); + end_pos = efl_canvas_text_cursor_position_get(sel_end); + if (start_pos <= end_pos) { pos = start_pos; - sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_BEGIN; + sd->sel_handler_cursor = sel_start; } else { pos = end_pos; - sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_END; + sd->sel_handler_cursor = sel_end; } - if (pos != main_pos) - edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text", - EDJE_CURSOR_MAIN, pos); + efl_canvas_text_cursor_position_set(main_cur, pos); _selection_handlers_offset_calc(data, sd->start_handler, ev->canvas.x, ev->canvas.y); } @@ -3667,19 +3681,23 @@ _start_handler_mouse_move_cb(void *data, Evas_Event_Mouse_Move *ev = event_info; Evas_Coord ex, ey; Evas_Coord cx, cy; + Efl_Canvas_Text_Cursor *main_cur; int pos; + Eo *text_obj = edje_object_part_swallow_get(sd->entry_edje, "elm.text"); + main_cur = efl_canvas_text_cursor_get(text_obj); + evas_object_geometry_get(sd->entry_edje, &ex, &ey, NULL, NULL); cx = ev->cur.canvas.x - sd->ox - ex; cy = ev->cur.canvas.y - sd->oy - ey; if (cx <= 0) cx = 1; - edje_object_part_text_cursor_coord_set(sd->entry_edje, "elm.text", - sd->sel_handler_cursor, cx, cy); - pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - sd->sel_handler_cursor); - edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text", - EDJE_CURSOR_MAIN, pos); + efl_canvas_text_cursor_coord_set(sd->sel_handler_cursor, cx, cy); + pos = efl_canvas_text_cursor_position_get(sd->sel_handler_cursor); + + /* Set the main cursor. */ + efl_canvas_text_cursor_position_set(main_cur, pos); + ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del); sd->long_pressed = EINA_FALSE; if (_elm_config->magnifier_enable) @@ -3695,28 +3713,32 @@ _end_handler_mouse_down_cb(void *data, EFL_UI_TEXT_DATA_GET(data, sd); Evas_Event_Mouse_Down *ev = event_info; - int pos, start_pos, end_pos, main_pos; + Efl_Canvas_Text_Cursor *sel_start, *sel_end; + Efl_Canvas_Text_Cursor *main_cur; + int pos, start_pos, end_pos; sd->end_handler_down = EINA_TRUE; - start_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - EDJE_CURSOR_SELECTION_BEGIN); - end_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - EDJE_CURSOR_SELECTION_END); + + Eo *text_obj = edje_object_part_swallow_get(sd->entry_edje, "elm.text"); + + efl_ui_text_interactive_selection_cursors_get(text_obj, &sel_start, &sel_end); + main_cur = efl_canvas_text_cursor_get(text_obj); + + start_pos = efl_canvas_text_cursor_position_get(sel_start); + end_pos = efl_canvas_text_cursor_position_get(sel_end); + if (start_pos < end_pos) { pos = end_pos; - sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_END; + sd->sel_handler_cursor = sel_start; } else { pos = start_pos; - sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_BEGIN; + sd->sel_handler_cursor = sel_end; } - main_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - EDJE_CURSOR_MAIN); - if (pos != main_pos) - edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text", - EDJE_CURSOR_MAIN, pos); + + efl_canvas_text_cursor_position_set(main_cur, pos); _selection_handlers_offset_calc(data, sd->end_handler, ev->canvas.x, ev->canvas.y); } @@ -3757,12 +3779,12 @@ _end_handler_mouse_move_cb(void *data, cy = ev->cur.canvas.y - sd->oy - ey; if (cx <= 0) cx = 1; - edje_object_part_text_cursor_coord_set(sd->entry_edje, "elm.text", - sd->sel_handler_cursor, cx, cy); - pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", - sd->sel_handler_cursor); - edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text", - EDJE_CURSOR_MAIN, pos); + efl_canvas_text_cursor_coord_set(sd->sel_handler_cursor, cx, cy); + pos = efl_canvas_text_cursor_position_get(sd->sel_handler_cursor); + /* Set the main cursor. */ + efl_canvas_text_cursor_position_set( + edje_object_part_swallow_get(sd->entry_edje, "elm.text"), + pos); ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del); sd->long_pressed = EINA_FALSE; if (_elm_config->magnifier_enable) @@ -3772,7 +3794,7 @@ _end_handler_mouse_move_cb(void *data, EOLIAN static void _efl_ui_text_evas_object_smart_add(Eo *obj, Efl_Ui_Text_Data *priv) { - Eo *ui_text; + Eo *text_obj; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); @@ -3798,14 +3820,16 @@ _efl_ui_text_evas_object_smart_add(Eo *obj, Efl_Ui_Text_Data *priv) if (!elm_layout_theme_set(obj, "efl_ui_text", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); - ui_text = eo_add(EFL_UI_INTERNAL_TEXT_INTERACTIVE_CLASS, obj); - eo_composite_attach(obj, ui_text); - edje_object_part_swallow(priv->entry_edje, "elm.text", ui_text); - efl_canvas_text_style_set(ui_text, "font=Sans font_size=14 color=#fff wrap=word"); - eo_event_callback_add(ui_text, EFL_UI_TEXT_INTERACTIVE_EVENT_CHANGED_USER, - _efl_ui_text_changed_cb, priv); - eo_event_callback_add(efl_canvas_text_cursor_get(ui_text), EFL_CANVAS_TEXT_CURSOR_EVENT_CHANGED, - _text_cursor_changed_cb, priv); + text_obj = eo_add(EFL_UI_INTERNAL_TEXT_INTERACTIVE_CLASS, obj); + eo_composite_attach(obj, text_obj); + edje_object_part_swallow(priv->entry_edje, "elm.text", text_obj); + efl_canvas_text_style_set(text_obj, "font=Sans font_size=14 color=#fff wrap=word"); + eo_event_callback_add(text_obj, EFL_UI_TEXT_INTERACTIVE_EVENT_CHANGED_USER, + _efl_ui_text_changed_cb, obj); + eo_event_callback_add(text_obj, EFL_UI_TEXT_INTERACTIVE_EVENT_SELECTION_CHANGED, + _efl_ui_text_selection_changed_cb, obj); + eo_event_callback_add(efl_canvas_text_cursor_get(text_obj), EFL_CANVAS_TEXT_CURSOR_EVENT_CHANGED, + _efl_ui_text_cursor_changed_cb, obj); priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj)); @@ -5832,12 +5856,20 @@ _efl_ui_text_elm_interface_atspi_accessible_name_get(Eo *obj, Efl_Ui_Text_Data * } static inline Eo * -_cursor_create(Eo *obj, Efl_Ui_Text_Data *sd, const char *file, const char *source) +_decoration_create(Eo *obj, Efl_Ui_Text_Data *sd, const char *file, + const char *source, Eina_Bool above) { Eo *ret = eo_add(EDJE_OBJECT_CLASS, obj); edje_object_file_set(ret, file, source); evas_object_smart_member_add(ret, obj); - evas_object_stack_above(ret, sd->entry_edje); + if (above) + { + evas_object_stack_above(ret, sd->entry_edje); + } + else + { + evas_object_stack_below(ret, sd->entry_edje); + } evas_object_clip_set(ret, evas_object_clip_get(obj)); evas_object_pass_events_set(ret, EINA_TRUE); return ret; @@ -5851,29 +5883,27 @@ _create_text_cursors(Eo *obj, Efl_Ui_Text_Data *sd) { const char *file; efl_file_get(sd->entry_edje, &file, NULL); - sd->cursor = _cursor_create(obj, sd, file, "elm/entry/cursor/default"); - sd->cursor_bidi = _cursor_create(obj, sd, file, "elm/entry/cursor/default"); + sd->cursor = _decoration_create(obj, sd, file, "elm/entry/cursor/default", EINA_TRUE); + sd->cursor_bidi = _decoration_create(obj, sd, file, "elm/entry/cursor/default", EINA_TRUE); evas_object_show(sd->cursor); evas_object_show(sd->cursor_bidi); edje_object_signal_emit(sd->cursor, "elm,action,focus", "elm"); edje_object_signal_emit(sd->cursor_bidi, "elm,action,focus", "elm"); } -/** - * General function to be called whenever decorations are requried to be - * updated. Example cases are resizes, key events, change events etc. - */ static void -_update_text_cursors(Efl_Ui_Text_Data *sd) +_update_text_cursors(Eo *obj) { Evas_Coord x, y, w, h, xx, yy, ww, hh; Evas_Coord xx2, yy2; - Eo *text_obj; Eina_Bool bidi_cursor; + EFL_UI_TEXT_DATA_GET(obj, sd); + + Eo *text_obj = edje_object_part_swallow_get(sd->entry_edje, "elm.text"); + x = y = w = h = -1; xx = yy = ww = hh = -1; - text_obj = edje_object_part_swallow_get(sd->entry_edje, "elm.text"); evas_object_geometry_get(text_obj, &x, &y, &w, &h); //FIXME; HACKKK!!! x = 0; y = 0; @@ -5906,22 +5936,105 @@ _update_text_cursors(Efl_Ui_Text_Data *sd) } static void -_update_decorations(Efl_Ui_Text_Data *sd) +_update_text_selection(Eo *obj, Eo *text_obj) +{ + Evas_Coord x, y; + Efl_Canvas_Text_Cursor *sel_start, *sel_end; + + Eina_List *l; + Eina_Iterator *range; + Efl_Ui_Text_Rectangle *rect; + Eina_Rectangle *r; + const char *file; + + EFL_UI_TEXT_DATA_GET(obj, sd); + + evas_object_geometry_get(text_obj, &x, &y, NULL, NULL); + + efl_file_get(sd->entry_edje, &file, NULL); + + efl_ui_text_interactive_selection_cursors_get(text_obj, &sel_start, &sel_end); + +#if 1 + { + int pos_start, pos_end; + + pos_start = efl_canvas_text_cursor_position_get(sel_start); + pos_end = efl_canvas_text_cursor_position_get(sel_end); + + printf("start=%d, end=%d\n", pos_start, pos_end); + } +#endif + + range = efl_canvas_text_range_geometry_get(text_obj, + sel_start, sel_end); + + l = sd->rects; + EINA_ITERATOR_FOREACH(range, r) + { + /* Create if there isn't a rectangle to populate. */ + if (!l) + { + rect = calloc(1, sizeof(Efl_Ui_Text_Rectangle)); + sd->rects = eina_list_append(sd->rects, rect); + + rect->obj_bg = _decoration_create(obj, sd, file, "elm/entry/selection/default", EINA_FALSE); + } + else + { + rect = eina_list_data_get(l); + l = l->next; + } + rect->rect = *r; + + if (rect->obj_bg) + { + evas_object_move(rect->obj_bg, x + r->x, y + r->y); + evas_object_resize(rect->obj_bg, r->w, r->h); + } + } + eina_iterator_free(range); + + /* delete redundant rectection rects */ + while (l) + { + Eina_List *temp = l->next; + rect = eina_list_data_get(l); + if (rect) + { + if (rect->obj_bg) eo_del(rect->obj_bg); + free(rect); + } + sd->rects = eina_list_remove_list(sd->rects, l); + l = temp; + } +} + +static void +_update_decorations(Eo *en_obj, Eo *text_obj) { - _update_text_cursors(sd); + _update_text_cursors(en_obj); + _update_text_selection(en_obj, text_obj); +} + +static Eina_Bool +_efl_ui_text_changed_cb(void *data, const Eo_Event *event EINA_UNUSED) +{ + _update_decorations(data, event->object); + return EINA_TRUE; } static Eina_Bool -_efl_ui_text_changed_cb(void *data EINA_UNUSED, const Eo_Event *event EINA_UNUSED) +_efl_ui_text_cursor_changed_cb(void *data, const Eo_Event *event EINA_UNUSED) { - _update_decorations(data); + _update_text_cursors(data); return EINA_TRUE; } static Eina_Bool -_text_cursor_changed_cb(void *data EINA_UNUSED, const Eo_Event *event EINA_UNUSED) +_efl_ui_text_selection_changed_cb(void *data, const Eo_Event *event EINA_UNUSED) { - _update_decorations(data); + _update_text_selection(data, event->object); return EINA_TRUE; } |