summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hirt <daniel.hirt@samsung.com>2016-03-29 16:53:41 +0300
committerDaniel Hirt <daniel.hirt@samsung.com>2016-03-31 18:09:10 +0300
commit8d1a8f0f64d8dea36070e676470247bd14b13a6f (patch)
tree17b03d6dbb1f6ec2ded3005ea1887f990e573214
parent18c208c7f94a20133f6ded4678371fb82d40cbf8 (diff)
downloadefl-devs/herdsman/tb2_annotation.tar.gz
Evas textblock: add annotation APIdevs/herdsman/tb2_annotation
The annotation API allows applying a format to a range in the text. Consider the following sequence of calls: evas_object_textblock_text_markup_set(tb, "hello world"); evas_object_textblock_annotation_set(tb, 0, 2, "color=#0ff"); evas_object_textblock_annotation_set(tb, 5, 6, "font_weight=Bold"); The above is the equivalent of the call: evas_object_textblock_text_markup_set(tb, "<color=#0ff>hel</color=#0ff>lo" " w<font_weight=Bold>or</font_weight=Bold>ld"); @feature
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c107
-rw-r--r--src/lib/evas/canvas/evas_textblock.eo37
-rw-r--r--src/tests/evas/evas_test_textblock.c52
3 files changed, 196 insertions, 0 deletions
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index a30ca1366f..0cf1b3f87b 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -9542,6 +9542,20 @@ _evas_textblock_cursor_is_at_the_end(const Evas_Textblock_Cursor *cur)
EINA_TRUE : EINA_FALSE;
}
+#warning remove this
+#if 0
+static void
+_nodes_format_print_all(Evas_Object_Textblock_Node_Text *node)
+{
+ Evas_Textblock_Node_Format *fnode;
+ printf("Text Node %p:\n", node);
+ EINA_INLIST_FOREACH(node->format_node, fnode)
+ {
+ printf("-- Format Node %p (Text Node: %p): offset=%lu \n", fnode, fnode->text_node, fnode->offset);
+ }
+}
+#endif
+
EAPI Eina_Bool
evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *format)
{
@@ -9674,6 +9688,10 @@ evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *form
if (!o->cursor->node)
o->cursor->node = o->text_nodes;
+#warning remove this
+#if 0
+ _nodes_format_print_all(cur->node);
+#endif
return is_visible;
}
@@ -12846,6 +12864,95 @@ _evas_textblock_evas_object_paragraph_direction_get(Eo *eo_obj EINA_UNUSED,
return o->paragraph_direction;
}
+/* Annotation API - WIP */
+EOLIAN static Eina_Bool
+_evas_textblock_annotation_set(Eo *eo_obj, Evas_Textblock_Data *o,
+ int start, int end EINA_UNUSED, char *format)
+{
+ int len;
+ char *buf;
+ Evas_Textblock_Cursor *cur;
+
+ if (!format || (format[0] == '\0')) return EINA_TRUE;
+
+ if ((end >= 0) && (end <= start)) return EINA_FALSE;
+ cur = evas_obj_textblock_cursor_new(eo_obj);
+
+ /* Add opening format at 'start' */
+ evas_textblock_cursor_pos_set(cur, start);
+ len = strlen(format);
+ buf = malloc(len + 3);
+ sprintf(buf, "<%s>", format);
+ evas_textblock_cursor_format_append(cur, buf);
+ free(buf);
+
+ /* Only close the format if (end >= 0) */
+ if (end >= 0)
+ {
+ evas_textblock_cursor_pos_set(cur, end + 1);
+ len = strlen(format);
+ buf = malloc(len + 4);
+ sprintf(buf, "</%s>", format);
+ evas_textblock_cursor_format_append(cur, buf);
+ free(buf);
+ }
+ evas_textblock_cursor_free(cur);
+ _evas_textblock_changed(o, eo_obj);
+
+ return EINA_TRUE;
+}
+
+EOLIAN static char *
+_evas_textblock_annotation_get(Eo *eo_obj EINA_UNUSED, Evas_Textblock_Data *o EINA_UNUSED,
+ int start EINA_UNUSED, int end EINA_UNUSED)
+{
+ const Evas_Object_Textblock_Node_Text *node;
+ const Evas_Object_Textblock_Node_Format *itr;
+ size_t npos, pos;
+ char *ret;
+ Eina_Bool first = EINA_TRUE;
+
+ Evas_Textblock_Cursor *cur = evas_object_textblock_cursor_new(eo_obj);
+ Eina_Strbuf *buf = eina_strbuf_new();
+
+ evas_textblock_cursor_pos_set(cur, start);
+
+ node = cur->node;
+ pos = npos = start - cur->pos;
+ EINA_INLIST_FOREACH(cur->node->format_node, itr)
+ {
+ while (itr->text_node != node)
+ {
+ npos += eina_ustrbuf_length_get(node->unicode);
+ node = _NODE_TEXT(EINA_INLIST_GET(node)->next);
+ pos = npos;
+ }
+ pos += itr->offset;
+ if (pos > (size_t) end) break;
+ if (pos >= (size_t) start)
+ {
+ if (!first)
+ {
+ eina_strbuf_append(buf, " ");
+ }
+ else
+ {
+ first = EINA_FALSE;
+ }
+ if (!itr->opener)
+ {
+ eina_strbuf_append(buf, "/");
+ }
+ eina_strbuf_append(buf, itr->format);
+ }
+ }
+ evas_textblock_cursor_free(cur);
+ ret = eina_strbuf_string_steal(buf);
+ eina_strbuf_free(buf);
+
+ return ret;
+}
+
/**
* @}
*/
diff --git a/src/lib/evas/canvas/evas_textblock.eo b/src/lib/evas/canvas/evas_textblock.eo
index a087400414..e61322a604 100644
--- a/src/lib/evas/canvas/evas_textblock.eo
+++ b/src/lib/evas/canvas/evas_textblock.eo
@@ -192,6 +192,43 @@ class Evas.Textblock (Evas.Object)
b: Evas.Coord;
}
}
+ @property annotation {
+ [[Annotation format in a given range in the text
+
+ The annotation $format begins at $start and usually closes at
+ $end (inclusive).
+
+ @since 1.18
+ ]]
+
+ set {
+ [[Sets an annotation format in a specified range [$start, $end]
+ in the text.
+
+ This will add both opening and closing formats for the given
+ $format. There is an option to given a negative value for $end,
+ in which case there will be no closing format, that is, the format
+ will be applied all the way to the end of the text until it will
+ be closed in a later call.
+ ]]
+ return: bool;
+ }
+ get {
+ [[Retrieves the annotation format instances that exist in the given
+ range [$start, $end]. The returned string may be a space-separated
+ list if multiple format instances were added in that range.
+ Note that formats that take effect in that range, but were not
+ added in it (i.e. they were added before) will not be included.
+ ]]
+ }
+ keys {
+ start: int;
+ end: int;
+ }
+ values {
+ format: char *;
+ }
+ }
line_number_geometry_get @const {
[[Get the geometry of a line number.]]
return: bool; [[$true on success, $false otherwise.]]
diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c
index 1473f99354..fa79718db0 100644
--- a/src/tests/evas/evas_test_textblock.c
+++ b/src/tests/evas/evas_test_textblock.c
@@ -3952,6 +3952,57 @@ START_TEST(evas_textblock_hyphenation)
END_TEST;
#endif
+static void
+_test_check_annotation(Evas_Object *tb,
+ int start, int end, const char *format)
+{
+ char *tmp = evas_object_textblock_annotation_get(tb, start, end);
+ ck_assert_msg(!strcmp(format, tmp),
+ "format at range [%d, %d] \"%s\" doesn't match given format \"%s\".",
+ start, end, tmp, format);
+ if (tmp) free(tmp);
+}
+
+START_TEST(evas_textblock_annotation)
+{
+ START_TB_TEST();
+ const char *buf =
+ "This text will check annotation.<ps>"
+ "By \"annotating\" the text, we can apply formatting simply by"
+ " specifying a range (start, end) in the text, and the format we want"
+ " for it."
+ ;
+ evas_object_textblock_text_markup_set(tb, buf);
+ ck_assert(evas_object_textblock_annotation_set(tb, 0, 3, NULL));
+ ck_assert(evas_object_textblock_annotation_set(tb, 0, 3, ""));
+ ck_assert(!evas_object_textblock_annotation_set(tb, 1, 0, "color=#fff"));
+
+ _test_check_annotation(tb, 0, 10, "");
+
+ evas_object_textblock_annotation_set(tb, 0, 3, "font_weight=bold");
+ _test_check_annotation(tb, 0, 3, "font_weight=bold");
+ _test_check_annotation(tb, 1, 3, "");
+
+ evas_object_textblock_annotation_set(tb, 50, 60, "color=#0ff");
+ _test_check_annotation(tb, 0, 49, "font_weight=bold /font_weight=bold ps");
+ _test_check_annotation(tb, 0, 50, "font_weight=bold /font_weight=bold ps color=#0ff");
+ _test_check_annotation(tb, 0, 51, "font_weight=bold /font_weight=bold ps color=#0ff");
+ _test_check_annotation(tb, 0, 59, "font_weight=bold /font_weight=bold ps color=#0ff");
+ _test_check_annotation(tb, 0, 60, "font_weight=bold /font_weight=bold ps color=#0ff");
+ _test_check_annotation(tb, 0, 61, "font_weight=bold /font_weight=bold ps color=#0ff /color=#0ff");
+ _test_check_annotation(tb, 40, 51, "color=#0ff");
+ _test_check_annotation(tb, 40, 61, "color=#0ff /color=#0ff");
+
+ evas_object_textblock_annotation_set(tb, 65, -1, "font_size=18");
+ _test_check_annotation(tb, 66, 1000, "");
+ _test_check_annotation(tb, 65, 1000, "font_size=18");
+ _test_check_annotation(tb, 64, 1000, "font_size=18");
+ _test_check_annotation(tb, 0, 1000, "font_weight=bold /font_weight=bold ps color=#0ff /color=#0ff font_size=18");
+
+ END_TB_TEST();
+}
+END_TEST;
+
void evas_test_textblock(TCase *tc)
{
tcase_add_test(tc, evas_textblock_simple);
@@ -3974,6 +4025,7 @@ void evas_test_textblock(TCase *tc)
tcase_add_test(tc, evas_textblock_items);
tcase_add_test(tc, evas_textblock_delete);
tcase_add_test(tc, evas_textblock_obstacle);
+ tcase_add_test(tc, evas_textblock_annotation);
#ifdef HAVE_HYPHEN
tcase_add_test(tc, evas_textblock_hyphenation);
#endif