Efl textblock/entry: Added support for split BiDi cursor.

If logical cursor is between LTR/RTL text two cursors will be shown.
  Upper cursor is shown for the text of the same direction as
  paragraph, lower cursor - for opposite.

  NOT DONE YET

Signed-off-by: Tom 'TAsn' Hacohen <tom@stosb.com>
This commit is contained in:
Tom 'TAsn' Hacohen 2013-01-14 16:18:07 +00:00 committed by Yakov Goldberg
parent afddaf94a0
commit a70abbb381
3 changed files with 134 additions and 3 deletions

View File

@ -21,7 +21,7 @@ struct _Entry
Edje_Real_Part *rp;
Edje *ed;
Evas_Object *cursor_bg;
Evas_Object *cursor_fg;
Evas_Object *cursor_fg, *cursor_fg2;
Evas_Textblock_Cursor *cursor;
Evas_Textblock_Cursor *sel_start, *sel_end;
Evas_Textblock_Cursor *cursor_user, *cursor_user_extra;
@ -2406,12 +2406,26 @@ _edje_entry_real_part_init(Edje *ed, Edje_Real_Part *rp)
evas_object_pass_events_set(en->cursor_fg, EINA_TRUE);
_edje_subobj_register(ed, en->cursor_fg);
/* A proxy to the main cursor. */
if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
{
en->cursor_fg2 = evas_object_image_add(rp->edje->base->evas);
evas_object_image_source_set(en->cursor_fg2, en->cursor_fg);
evas_object_image_fill_set(en->cursor_fg2, 0, 0, 1, 1);
evas_object_smart_member_add(en->cursor_fg2, rp->edje->obj);
evas_object_stack_above(en->cursor_fg2, rp->object);
evas_object_clip_set(en->cursor_fg2, evas_object_clip_get(rp->object));
evas_object_pass_events_set(en->cursor_fg2, EINA_TRUE);
_edje_subobj_register(en->rp->edje, en->cursor_fg2);
}
evas_object_textblock_legacy_newline_set(rp->object, EINA_TRUE);
if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
{
evas_object_show(en->cursor_bg);
evas_object_show(en->cursor_fg);
evas_object_show(en->cursor_fg2);
en->input_panel_enable = EINA_TRUE;
#ifdef HAVE_ECORE_IMF
@ -2487,6 +2501,7 @@ _edje_entry_real_part_shutdown(Edje *ed, Edje_Real_Part *rp)
#endif
evas_object_del(en->cursor_bg);
evas_object_del(en->cursor_fg);
evas_object_del(en->cursor_fg2);
if (en->pw_timer)
{
@ -2519,9 +2534,10 @@ _edje_entry_real_part_shutdown(Edje *ed, Edje_Real_Part *rp)
void
_edje_entry_real_part_configure(Edje *ed, Edje_Real_Part *rp)
{
Evas_Coord x, y, w, h, xx, yy, ww, hh;
Evas_Coord x, y, w, h, xx, yy, ww, hh, xx2, yy2;
Entry *en;
Evas_Textblock_Cursor_Type cur_type;
Eina_Bool bidi_cursor = EINA_FALSE;
if ((rp->type != EDJE_RP_TYPE_TEXT) ||
(!rp->typedata.text)) return;
@ -2543,7 +2559,7 @@ _edje_entry_real_part_configure(Edje *ed, Edje_Real_Part *rp)
x = y = w = h = -1;
xx = yy = ww = hh = -1;
evas_object_geometry_get(rp->object, &x, &y, &w, &h);
evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, NULL, cur_type);
bidi_cursor = evas_textblock_cursor_geometry_bidi_get(en->cursor, &xx, &yy, &ww, &hh, &xx2, &yy2, NULL, NULL, cur_type);
if (ww < 1) ww = 1;
if (hh < 1) hh = 1;
if (en->cursor_bg)
@ -2556,6 +2572,22 @@ _edje_entry_real_part_configure(Edje *ed, Edje_Real_Part *rp)
evas_object_move(en->cursor_fg, x + xx, y + yy);
evas_object_resize(en->cursor_fg, ww, hh);
}
if (en->cursor_fg2)
{
if (bidi_cursor)
{
evas_object_image_fill_set(en->cursor_fg2, 0, 0, ww, hh / 2);
evas_object_move(en->cursor_fg2, x + xx2, y + yy2 + (hh / 2));
evas_object_resize(en->cursor_fg, ww, hh / 2);
evas_object_resize(en->cursor_fg2, ww, hh / 2);
evas_object_show(en->cursor_fg2);
}
else
{
evas_object_hide(en->cursor_fg2);
}
}
}
const char *

View File

@ -11628,6 +11628,11 @@ EAPI char *evas_textblock_cursor_range_text_g
*/
EAPI char *evas_textblock_cursor_content_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
/** FIXME: doc.
* The cw2 and etc are not valid if false is returned. */
EAPI Eina_Bool
evas_textblock_cursor_geometry_bidi_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_Coord *cx2, Evas_Coord *cy2, Evas_Coord *cw2, Evas_Coord *ch2, Evas_Textblock_Cursor_Type ctype);
/**
* Returns the geometry of the cursor. Depends on the type of cursor requested.
* This should be used instead of char_geometry_get because there are weird

View File

@ -8950,6 +8950,100 @@ evas_textblock_cursor_format_is_visible_get(const Evas_Textblock_Cursor *cur)
return EVAS_TEXTBLOCK_IS_VISIBLE_FORMAT_CHAR(text[cur->pos]);
}
EAPI Eina_Bool
evas_textblock_cursor_geometry_bidi_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_Coord *cx2, Evas_Coord *cy2, Evas_Coord *cw2, Evas_Coord *ch2, Evas_Textblock_Cursor_Type ctype)
{
const Evas_Textblock_Cursor *dir_cur;
Evas_Textblock_Cursor cur2;
if (!cur) return EINA_FALSE;
Evas_Object_Textblock *o = eo_data_get(cur->obj, MY_CLASS);
if (!o->formatted.valid) _relayout(cur->obj);
dir_cur = cur;
if (ctype == EVAS_TEXTBLOCK_CURSOR_UNDER)
{
evas_textblock_cursor_pen_geometry_get(cur, cx, cy, cw, ch);
return EINA_FALSE;
}
else
{
Evas_Object_Textblock_Line *ln = NULL;
Evas_Object_Textblock_Item *it = NULL;
_find_layout_item_match(cur, &ln, &it);
if (ln && it)
{
if (cw) *cw = 0;
if (cw2) *cw2 = 0;
/* If we are at the start or the end of the item there's a chance
* we'll want a split cursor.
* FIXME: Handle the last char of the last paragraph.
* FIXME: Handle multiple items of the same direction.
* FIXME: Handle items across different lines.. */
if (cur->pos == it->text_pos)
{
Evas_BiDi_Direction itdir = (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ?
_ITEM_TEXT(it)->text_props.bidi_dir : _ITEM_FORMAT(it)->bidi_dir;
Evas_Object_Textblock_Item *previt = NULL;
Evas_BiDi_Direction previtdir = EVAS_BIDI_DIRECTION_NEUTRAL;
/* Get the logically previous item. */
{
Eina_List *itr;
Evas_Object_Textblock_Item *ititr;
EINA_LIST_FOREACH(ln->par->logical_items, itr, ititr)
{
if (ititr == it)
break;
previt = ititr;
}
if (previt)
{
previtdir = (previt->type == EVAS_TEXTBLOCK_ITEM_TEXT) ?
_ITEM_TEXT(previt)->text_props.bidi_dir : _ITEM_FORMAT(previt)->bidi_dir;
}
}
if (previt && (itdir != previtdir))
{
Evas_Object_Textblock_Item *curit = NULL;
/* If the current dir is different than the paragraph dir
* this is our item. */
if (itdir != ln->par->direction)
{
curit = it;
}
else
{
curit = previt;
}
if (((curit == it) && (ln->par->direction == EVAS_BIDI_DIRECTION_LTR)) ||
((curit == previt) && (ln->par->direction == EVAS_BIDI_DIRECTION_RTL)))
{
if (cx) *cx = ln->x + curit->x;
if (cx2) *cx2 = ln->x + curit->x + curit->w;
}
else
{
if (cx) *cx = ln->x + curit->x + curit->w;
if (cx2) *cx2 = ln->x + curit->x;
}
if (cy) *cy = ln->par->y + ln->y;
if (ch) *ch = curit->h;
if (cy2) *cy2 = ln->par->y + ln->y;
if (ch2) *ch2 = curit->h;
return EINA_TRUE;
}
}
}
}
evas_textblock_cursor_geometry_get(cur, cx, cy, cw, ch, NULL, ctype);
return EINA_FALSE;
}
EAPI int
evas_textblock_cursor_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_BiDi_Direction *dir, Evas_Textblock_Cursor_Type ctype)
{