diff options
author | Daniel Hirt <daniel.hirt@samsung.com> | 2016-05-03 17:03:46 +0300 |
---|---|---|
committer | Daniel Hirt <daniel.hirt@samsung.com> | 2016-05-16 11:17:56 +0300 |
commit | 2f47d249cac3c86c41c19bc0ca3d7d50584f5552 (patch) | |
tree | af1dfabc36c3f3d931b6a3a7647e6d48173bbc25 | |
parent | c26896311df402e8b452857c58708d3c10e0ec5e (diff) | |
download | efl-2f47d249cac3c86c41c19bc0ca3d7d50584f5552.tar.gz |
Evas textblock: add object_item API
The object item replaces the format item. Normal usage of adding items that
occupy space in the text is now blocked from annotation. This means that formats
like "<item ...>" are not supported via annotation_insert/set.
Instead, use object_item_insert to add items. Another difference is that
you specify at which position you will add the item (and not a range, like in
annotation API).
Essentially, this adds the OBJECT_REPLACEMENT_CHARACTER (OBJ) and adds a format
to it, like it normally did. Also, you can query its annotation and get the
attributes of the item like "size=32x32", "vsize=..." etc. Deleting it will also
delete the inserted OBJ character, and vice-versa. So this API is pretty
self-contained and shouldn't feel uncomfortable to use.
@feature
-rw-r--r-- | src/lib/evas/canvas/evas_object_textblock.c | 74 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_textblock.eo | 15 | ||||
-rw-r--r-- | src/tests/evas/evas_test_textblock.c | 22 |
3 files changed, 98 insertions, 13 deletions
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index 4b08c6f1f9..586947ef5e 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -491,6 +491,7 @@ struct _Evas_Textblock_Annotation EINA_INLIST; Evas_Object *obj; Evas_Object_Textblock_Node_Format *start_node, *end_node; + Eina_Bool is_item : 1; /**< indicates it is an item/object placeholder */ }; /* Size of the index array */ @@ -4267,9 +4268,10 @@ _layout_do_format(const Evas_Object *obj EINA_UNUSED, Ctxt *c, const char *s; const char *item; int handled = 0; + Eina_Bool is_item = (n->annotation && n->annotation->is_item); s = n->format; - if (!strncmp(s, "item ", 5)) + if (!strncmp(s, "item ", 5) || is_item) { // one of: // item size=20x10 href=name @@ -4294,17 +4296,17 @@ _layout_do_format(const Evas_Object *obj EINA_UNUSED, Ctxt *c, // don't care //href = strstr(s, " href="); - p = strstr(s, " vsize="); + p = strstr(s, is_item ? "vsize=" : " vsize="); if (p) { - p += 7; + p += (is_item ? 6 : 7); if (!strncmp(p, "full", 4)) vsize = VSIZE_FULL; else if (!strncmp(p, "ascent", 6)) vsize = VSIZE_ASCENT; } - p = strstr(s, " size="); + p = strstr(s, is_item ? "size=" : " size="); if (p) { - p += 6; + p += (is_item ? 5 : 6); if (sscanf(p, "%ix%i", &w, &h) == 2) { /* this is handled somewhere else because it depends @@ -4316,10 +4318,10 @@ _layout_do_format(const Evas_Object *obj EINA_UNUSED, Ctxt *c, } else { - p = strstr(s, " absize="); + p = strstr(s, is_item ? "absize=" : " absize="); if (p) { - p += 8; + p += (is_item ? 7 : 8); if (sscanf(p, "%ix%i", &w, &h) == 2) { size = SIZE_ABS; @@ -4327,7 +4329,7 @@ _layout_do_format(const Evas_Object *obj EINA_UNUSED, Ctxt *c, } else { - p = strstr(s, " relsize="); + p = strstr(s, is_item ? "relsize=" : " relsize="); if (p) { /* this is handled somewhere else because it depends @@ -13268,6 +13270,14 @@ _textblock_annotation_set(Eo *eo_obj, Evas_Textblock_Data *o, int len; char *buf; Evas_Textblock_Node_Format *fnode; + + if (an->is_item) + { + ERR("Cannot reset format of \"item\" annotations. This is a special" + "annotation that should not be modified using this function"); + return EINA_FALSE; + } + Evas_Textblock_Cursor *cur = evas_obj_textblock_cursor_new(eo_obj); /* Add opening format at 'start' */ @@ -13329,7 +13339,10 @@ _evas_textblock_annotation_set(Eo *eo_obj EINA_UNUSED, _evas_textblock_node_format_remove(o, annotation->start_node, 0); _evas_textblock_node_format_remove(o, annotation->end_node, 0); - _textblock_annotation_set(eo_obj, o, annotation, start, end, format); + if (!_textblock_annotation_set(eo_obj, o, annotation, start, end, format)) + { + return EINA_FALSE; + } return EINA_TRUE; } @@ -13340,6 +13353,16 @@ _evas_textblock_annotation_remove(Evas_Textblock_Data *o, { if (remove_nodes) { + if (an->is_item) + { + /* Remove the OBJ character along with the cursor. */ + Evas_Textblock_Cursor *cur = evas_obj_textblock_cursor_new(an->obj); + size_t pos = _textblock_fnode_pos_get(o, an->start_node); + evas_textblock_cursor_pos_set(cur, pos); + evas_textblock_cursor_char_delete(cur); + evas_textblock_cursor_free(cur); + return; // 'an' should be deleted after char deletion. + } _evas_textblock_node_format_remove(o, an->start_node, 0); _evas_textblock_node_format_remove(o, an->end_node, 0); } @@ -13384,16 +13407,17 @@ _evas_textblock_annotation_del(Eo *eo_obj EINA_UNUSED, return EINA_TRUE; } -EOLIAN static Evas_Textblock_Annotation * -_evas_textblock_annotation_insert(Eo *eo_obj, Evas_Textblock_Data *o, - size_t start, size_t end EINA_UNUSED, const char *format) +static Evas_Textblock_Annotation * +_textblock_annotation_insert(Eo *eo_obj, Evas_Textblock_Data *o, + size_t start, size_t end EINA_UNUSED, const char *format, + Eina_Bool is_item) { Evas_Textblock_Annotation *ret = NULL; Eina_Strbuf *buf; Eina_Bool first = EINA_TRUE; const char *item; - if (!format || (format[0] == '\0') || (end <= start)) return NULL; + if (!format || (format[0] == '\0') || (end < start)) return NULL; /* Sanitize the string and reject format items, closing '/' marks. */ buf = eina_strbuf_new(); @@ -13434,12 +13458,21 @@ _evas_textblock_annotation_insert(Eo *eo_obj, Evas_Textblock_Data *o, EINA_INLIST_GET(ret)); _textblock_annotation_set(eo_obj, o, ret, start, end, format); + ret->is_item = is_item; _evas_textblock_changed(o, eo_obj); return ret; } +EOLIAN static Evas_Textblock_Annotation * +_evas_textblock_annotation_insert(Eo *eo_obj, Evas_Textblock_Data *o, + size_t start, size_t end EINA_UNUSED, const char *format) +{ + return _textblock_annotation_insert(eo_obj, o, start, end, format, + EINA_FALSE); +} + EOLIAN static Eina_Iterator * _evas_textblock_annotation_range_get_all(Eo *eo_obj EINA_UNUSED, Evas_Textblock_Data *o EINA_UNUSED, size_t start, size_t end) @@ -13461,6 +13494,21 @@ _evas_textblock_annotation_range_get_all(Eo *eo_obj EINA_UNUSED, Evas_Textblock_ return _evas_textblock_annotation_iterator_new(lst); } +EOLIAN static Evas_Textblock_Annotation * +_evas_textblock_object_item_insert(Eo *eo_obj EINA_UNUSED, + Evas_Textblock_Data *o EINA_UNUSED, size_t pos, const char *format) +{ + Evas_Textblock_Cursor *cur; + Evas_Textblock_Annotation *ret; + + cur = evas_obj_textblock_cursor_new(eo_obj); + evas_textblock_cursor_pos_set(cur, pos); + eina_ustrbuf_insert_char(cur->node->unicode, _REPLACEMENT_CHAR, cur->pos); + ret = _textblock_annotation_insert(eo_obj, o, pos, pos, format, EINA_TRUE); + + return ret; +} + /** * @} */ diff --git a/src/lib/evas/canvas/evas_textblock.eo b/src/lib/evas/canvas/evas_textblock.eo index 5ced9c3aa2..072e0b52eb 100644 --- a/src/lib/evas/canvas/evas_textblock.eo +++ b/src/lib/evas/canvas/evas_textblock.eo @@ -620,6 +620,21 @@ class Evas.Textblock (Evas.Object) @in y: Evas.Coord; [[y coord to set by.]] } } + object_item_insert { + [[Inserts a object item at specified position. + + This adds a placeholder to be queried by higher-level code, + which in turn place graphics on top of it. It essentially places an + OBJECT REPLACEMENT CHARACTER and set a special annotation to it. + ]] + return: Evas.Textblock.Annotation *; [[The annotation handle of the + inserted item.]] + params { + @in pos: size; [[Position of the inserted item.]] + @in format: const(char)*; [[Format of the inserted item. + See Format styles.]] + } + } style_user_peek @const { [[Get (don't remove) the style at the top of the user style stack. diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c index 814c96251f..5d8c410677 100644 --- a/src/tests/evas/evas_test_textblock.c +++ b/src/tests/evas/evas_test_textblock.c @@ -4089,6 +4089,28 @@ START_TEST(evas_textblock_annotation) an = evas_object_textblock_annotation_insert(tb, 6, 7, "item"); _test_check_annotation(tb, 0, 8, _COMP_PARAMS("color=#fff")); + /* Check "item" annotations */ + evas_object_textblock_text_markup_set(tb, "abcd"); + an = evas_object_textblock_object_item_insert(tb, 4, "size=16x16"); + _test_check_annotation(tb, 4, 4, _COMP_PARAMS("size=16x16")); + + /* Check that format is not extended if it's an "object item" */ + evas_textblock_cursor_pos_set(cur, 5); + evas_textblock_cursor_text_append(cur, "a"); + _test_check_annotation(tb, 5, 7, _COMP_PARAMS()); + _test_check_annotation(tb, 0, 3, _COMP_PARAMS()); + + /* Remove annotation of "item" also removes the OBJ character */ + { + int blen, len; + evas_textblock_cursor_pos_set(cur, 5); + blen = evas_textblock_cursor_paragraph_text_length_get(cur); + evas_object_textblock_annotation_del(tb, an); + len = evas_textblock_cursor_paragraph_text_length_get(cur); + ck_assert_int_eq(len, blen - 1); + _test_check_annotation(tb, 0, 5, _COMP_PARAMS()); + } + END_TB_TEST(); } END_TEST; |