summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hirt <daniel.hirt@samsung.com>2016-05-03 17:03:46 +0300
committerDaniel Hirt <daniel.hirt@samsung.com>2016-05-16 11:17:56 +0300
commit2f47d249cac3c86c41c19bc0ca3d7d50584f5552 (patch)
treeaf1dfabc36c3f3d931b6a3a7647e6d48173bbc25
parentc26896311df402e8b452857c58708d3c10e0ec5e (diff)
downloadefl-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.c74
-rw-r--r--src/lib/evas/canvas/evas_textblock.eo15
-rw-r--r--src/tests/evas/evas_test_textblock.c22
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;