summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Alzyod <ali198724@gmail.com>2019-11-27 13:04:31 +0900
committerWooHyun Jung <wh0705.jung@samsung.com>2019-11-27 13:04:32 +0900
commitc7f37fe61852ea45dce071e0f80f98adcce08981 (patch)
tree964906c510dd0af5310157ab0ebbcc4c29d42543
parentf10c91cda9795a43e6984814b7394383cf9da812 (diff)
Efl.Text.Attribute_Factory
Summary: Implementation of new Efl.Text.Attribute_Factory class which replace the annotation interface. Currently, we have two public methods: ``` void efl_text_attribute_factory_attribute_insert(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end, const char *format) unsigned int efl_text_attribute_factory_attribute_clear(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end); ``` Other methods will be internal methods, for the time being, we will redesign internal methods Reviewers: woohyun, tasn, segfaultxavi, bu5hm4n, zmike Subscribers: zmike, q66, cedric, segfaultxavi, bu5hm4n, a.srour, #committers, #reviewers Tags: #efl Differential Revision: https://phab.enlightenment.org/D10646
-rw-r--r--src/bin/elementary/test.c2
-rw-r--r--src/bin/elementary/test_efl_ui_text.c162
-rw-r--r--src/lib/efl/Efl.h3
-rw-r--r--src/lib/efl/interfaces/efl_interfaces_main.c1
-rw-r--r--src/lib/efl/interfaces/efl_text_annotate.eo137
-rw-r--r--src/lib/efl/interfaces/efl_text_types.eot4
-rw-r--r--src/lib/efl/interfaces/meson.build1
-rw-r--r--src/lib/elementary/efl_ui_internal_text_interactive.c1
-rw-r--r--src/lib/elementary/efl_ui_text.c78
-rw-r--r--src/lib/evas/Efl_Canvas.h1
-rw-r--r--src/lib/evas/Evas_Eo.h1
-rw-r--r--src/lib/evas/Evas_Internal.h11
-rw-r--r--src/lib/evas/canvas/efl_canvas_text.eo11
-rw-r--r--src/lib/evas/canvas/efl_canvas_text_internal.h104
-rw-r--r--src/lib/evas/canvas/efl_text_attribute_factory.c133
-rw-r--r--src/lib/evas/canvas/efl_text_attribute_factory.eo37
-rw-r--r--src/lib/evas/canvas/efl_text_cursor.c10
-rw-r--r--src/lib/evas/canvas/efl_text_cursor.eo13
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c303
-rw-r--r--src/lib/evas/canvas/meson.build4
-rw-r--r--src/tests/evas/evas_test_textblock.c224
21 files changed, 431 insertions, 810 deletions
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index a78850a..1d91bf5 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -366,7 +366,6 @@ void test_code_diff_inline(void *data, Evas_Object *obj, void *event_info);
366void test_efl_ui_text(void *data, Evas_Object *obj, void *event_info); 366void test_efl_ui_text(void *data, Evas_Object *obj, void *event_info);
367void test_efl_ui_text_inputfield(void *data, Evas_Object *obj, void *event_info); 367void test_efl_ui_text_inputfield(void *data, Evas_Object *obj, void *event_info);
368void test_efl_ui_text_label(void *data, Evas_Object *obj, void *event_info); 368void test_efl_ui_text_label(void *data, Evas_Object *obj, void *event_info);
369void test_ui_text_item_factory(void *data, Evas_Object *obj, void *event_info);
370void test_evas_mask(void *data, Edje_Object *obj, void *event_info); 369void test_evas_mask(void *data, Edje_Object *obj, void *event_info);
371void test_gfx_filters(void *data, Evas_Object *obj, void *event_info); 370void test_gfx_filters(void *data, Evas_Object *obj, void *event_info);
372void test_evas_snapshot(void *data, Evas_Object *obj, void *event_info); 371void test_evas_snapshot(void *data, Evas_Object *obj, void *event_info);
@@ -941,7 +940,6 @@ add_tests:
941 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text", test_efl_ui_text); 940 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text", test_efl_ui_text);
942 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text Input Field", test_efl_ui_text_inputfield); 941 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text Input Field", test_efl_ui_text_inputfield);
943 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text Label", test_efl_ui_text_label); 942 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text Label", test_efl_ui_text_label);
944 ADD_TEST_EO(NULL, "Entries", "Ui.Text Item Factory", test_ui_text_item_factory);
945 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Tags", test_ui_tags); 943 ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Tags", test_ui_tags);
946 944
947 //------------------------------// 945 //------------------------------//
diff --git a/src/bin/elementary/test_efl_ui_text.c b/src/bin/elementary/test_efl_ui_text.c
index d56fddb..e060067 100644
--- a/src/bin/elementary/test_efl_ui_text.c
+++ b/src/bin/elementary/test_efl_ui_text.c
@@ -5,6 +5,7 @@
5#include <Efl_Ui.h> 5#include <Efl_Ui.h>
6#include <Elementary.h> 6#include <Elementary.h>
7#include "elm_priv.h" //FIXME remove this once efl.ui.text doesn't need elm_general.h 7#include "elm_priv.h" //FIXME remove this once efl.ui.text doesn't need elm_general.h
8
8static void 9static void
9_apply_style(Eo *obj, size_t start_pos, size_t end_pos, const char *style) 10_apply_style(Eo *obj, size_t start_pos, size_t end_pos, const char *style)
10{ 11{
@@ -16,7 +17,7 @@ _apply_style(Eo *obj, size_t start_pos, size_t end_pos, const char *style)
16 efl_text_cursor_position_set(start, start_pos); 17 efl_text_cursor_position_set(start, start_pos);
17 efl_text_cursor_position_set(end, end_pos); 18 efl_text_cursor_position_set(end, end_pos);
18 19
19 efl_text_annotation_insert(obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end), style); 20 efl_text_attribute_factory_attribute_insert(start, end, style);
20 21
21 efl_del(start); 22 efl_del(start);
22 efl_del(end); 23 efl_del(end);
@@ -235,162 +236,3 @@ test_efl_ui_text_inputfield(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED
235 efl_gfx_entity_size_set(win, EINA_SIZE2D(300, 200)); 236 efl_gfx_entity_size_set(win, EINA_SIZE2D(300, 200));
236 237
237} 238}
238
239#define IMAGES_SZ 5
240
241static const char *images[IMAGES_SZ] = {
242 "sky", "logo", "dog", "eet_rock", "eet_plant" };
243
244static void
245_on_factory_bt_image_clicked(void *data, const Efl_Event *event EINA_UNUSED)
246{
247 Evas_Object *en = data;
248 static int image_idx = 0;
249
250 image_idx = (image_idx + 1) % IMAGES_SZ;
251
252 efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(efl_text_interactive_main_cursor_get(en)),
253 images[image_idx], "size=32x32");
254 printf("Inserted image: key = %s\n", images[image_idx]);
255}
256
257static void
258_on_factory_bt_emoticon_clicked(void *data, const Efl_Event *event EINA_UNUSED)
259{
260 Evas_Object *en = data;
261 efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(efl_text_interactive_main_cursor_get(en)),
262 "emoticon/evil-laugh", "size=32x32");
263}
264
265static struct
266{
267 const char *name;
268 Eo *item_factory;
269} factories[3];
270
271static void
272_on_factory_bt_factory_clicked(void *data, const Efl_Event *event EINA_UNUSED)
273{
274 Evas_Object *en = data;
275 static int item_factory_idx = 0;
276
277 item_factory_idx = (item_factory_idx + 1) % 3;
278 efl_ui_text_item_factory_set(en, factories[item_factory_idx].item_factory);
279 printf("Factory set to: %s\n", factories[item_factory_idx].name);
280}
281
282#define FACTORY_NONE 0
283#define FACTORY_IMAGE 1
284#define FACTORY_EMOTICON 2
285
286void
287test_ui_text_item_factory(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
288{
289 Evas_Object *win, *bx, *bx2, *bt, *en;
290 Efl_Text_Cursor *main_cur, *cur;
291 char buf[128];
292 Eina_File *f;
293
294 win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
295 efl_text_set(efl_added, "Efl Ui Text Item Factory"),
296 efl_ui_win_autodel_set(efl_added, EINA_TRUE));
297
298 bx = efl_add(EFL_UI_BOX_CLASS, win);
299 efl_content_set(win, bx);
300
301 en = efl_add(EFL_UI_TEXT_CLASS, bx,
302 efl_text_multiline_set(efl_added, EINA_TRUE));
303
304 factories[FACTORY_NONE].name = "None (Fallback)";
305 factories[FACTORY_NONE].item_factory = NULL;
306
307 factories[FACTORY_IMAGE].name = "Image Factory";
308 factories[FACTORY_IMAGE].item_factory =
309 efl_add(EFL_UI_TEXT_FACTORY_IMAGES_CLASS, en);
310
311 factories[FACTORY_EMOTICON].name = "Emoticon Factory";
312 factories[FACTORY_EMOTICON].item_factory =
313 efl_add(EFL_UI_TEXT_FACTORY_EMOTICONS_CLASS, en);
314
315 // Test assigning file path source
316 snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", elm_app_data_dir_get());
317 efl_ui_text_factory_images_matches_add(factories[FACTORY_IMAGE].item_factory,
318 images[0], buf, NULL);
319 snprintf(buf, sizeof(buf), "%s/images/logo.png", elm_app_data_dir_get());
320 efl_ui_text_factory_images_matches_add(factories[FACTORY_IMAGE].item_factory,
321 images[1], buf, NULL);
322 snprintf(buf, sizeof(buf), "%s/images/mystrale.jpg", elm_app_data_dir_get());
323 efl_ui_text_factory_images_matches_add(factories[FACTORY_IMAGE].item_factory,
324 images[2], buf, NULL);
325
326 // Open EET source w/ key
327 snprintf(buf, sizeof(buf), "%s/images/image_items.eet", elm_app_data_dir_get());
328 f = eina_file_open(buf, EINA_FALSE);
329 if (f)
330 {
331 efl_ui_text_factory_images_matches_mmap_add(
332 factories[FACTORY_IMAGE].item_factory,
333 "eet_rock", f, "rock");
334 efl_ui_text_factory_images_matches_mmap_add(
335 factories[FACTORY_IMAGE].item_factory,
336 "eet_plant", f, "plant");
337 eina_file_close(f);
338 }
339 else
340 {
341 printf("Error loading test file. Please review test.");
342 }
343
344
345 printf("Added Efl.Ui.Text object\n");
346 efl_text_set(en, "Hello world! Goodbye world! This is a test text for the"
347 " new UI Text widget.\xE2\x80\xA9This is the next paragraph.\nThis"
348 " is the next line.\nThis is Yet another line! Line and paragraph"
349 " separators are actually different!");
350 efl_text_font_set(en, "Sans", 14);
351 efl_text_normal_color_set(en, 255, 255, 255, 255);
352
353 main_cur = efl_text_interactive_main_cursor_get(en);
354 cur = efl_ui_text_cursor_create(en);
355
356 efl_text_cursor_position_set(cur, 2);
357 efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(cur), "emoticon/happy", "size=32x32");
358 efl_text_cursor_position_set(cur, 50);
359
360 snprintf(buf, sizeof(buf), "file://%s/images/sky_01.jpg", elm_app_data_dir_get());
361 efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(cur), buf, "size=32x32");
362 efl_text_cursor_position_set(main_cur, 5);
363
364 efl_text_interactive_editable_set(en, EINA_TRUE);
365 efl_ui_text_scrollable_set(en, EINA_TRUE);
366 efl_pack(bx, en);
367 elm_object_focus_set(en, EINA_TRUE);
368
369 bx2 = efl_add(EFL_UI_BOX_CLASS, bx);
370 efl_gfx_hint_weight_set(bx2, EFL_GFX_HINT_EXPAND, EFL_GFX_HINT_EXPAND);
371 efl_ui_layout_orientation_set(bx2, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
372
373 bt = efl_add(EFL_UI_BUTTON_CLASS, bx2);
374 efl_text_set(bt, "Image");
375 efl_event_callback_add(bt, EFL_INPUT_EVENT_CLICKED, _on_factory_bt_image_clicked, en);
376 efl_gfx_hint_weight_set(bt, EFL_GFX_HINT_EXPAND, 0.0);
377 efl_pack(bx2, bt);
378 elm_object_focus_allow_set(bt, EINA_FALSE);
379
380 bt = efl_add(EFL_UI_BUTTON_CLASS, bx2);
381 efl_text_set(bt, "Emoticon");
382 efl_event_callback_add(bt, EFL_INPUT_EVENT_CLICKED, _on_factory_bt_emoticon_clicked, en);
383 efl_gfx_hint_weight_set(bt, EFL_GFX_HINT_EXPAND, 0.0);
384 efl_pack(bx2, bt);
385 elm_object_focus_allow_set(bt, EINA_FALSE);
386
387 bt = efl_add(EFL_UI_BUTTON_CLASS, bx2);
388 efl_text_set(bt, "Factory");
389 efl_event_callback_add(bt, EFL_INPUT_EVENT_CLICKED, _on_factory_bt_factory_clicked, en);
390 efl_gfx_hint_weight_set(bt, EFL_GFX_HINT_EXPAND, 0.0);
391 efl_pack(bx2, bt);
392 elm_object_focus_allow_set(bt, EINA_FALSE);
393
394 efl_pack(bx, bx2);
395 efl_gfx_entity_size_set(win, EINA_SIZE2D(480, 320));
396}
diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h
index c78d105..a9970e2 100644
--- a/src/lib/efl/Efl.h
+++ b/src/lib/efl/Efl.h
@@ -70,7 +70,7 @@ typedef struct tm Efl_Time;
70 70
71typedef struct _Efl_Text_Cursor_Handle Efl_Text_Cursor_Handle; 71typedef struct _Efl_Text_Cursor_Handle Efl_Text_Cursor_Handle;
72typedef struct _Efl_Text_Cursor_Handle _Efl_Text_Cursor_Handle; 72typedef struct _Efl_Text_Cursor_Handle _Efl_Text_Cursor_Handle;
73typedef struct _Efl_Text_Annotate_Annotation Efl_Text_Annotate_Annotation; 73typedef struct _Efl_Text_Attribute_Handle Efl_Text_Attribute_Handle;
74 74
75#include "interfaces/efl_types.eot.h" 75#include "interfaces/efl_types.eot.h"
76 76
@@ -211,7 +211,6 @@ typedef Efl_Gfx_Path_Command_Type Efl_Gfx_Path_Command;
211#include "interfaces/efl_text_font.eo.h" 211#include "interfaces/efl_text_font.eo.h"
212#include "interfaces/efl_text_style.eo.h" 212#include "interfaces/efl_text_style.eo.h"
213#include "interfaces/efl_text_format.eo.h" 213#include "interfaces/efl_text_format.eo.h"
214#include "interfaces/efl_text_annotate.eo.h"
215#include "interfaces/efl_text_markup.eo.h" 214#include "interfaces/efl_text_markup.eo.h"
216#include "interfaces/efl_text_markup_util.eo.h" 215#include "interfaces/efl_text_markup_util.eo.h"
217 216
diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c b/src/lib/efl/interfaces/efl_interfaces_main.c
index 71162b9..3e94adc 100644
--- a/src/lib/efl/interfaces/efl_interfaces_main.c
+++ b/src/lib/efl/interfaces/efl_interfaces_main.c
@@ -24,7 +24,6 @@
24#include "interfaces/efl_text_font.eo.c" 24#include "interfaces/efl_text_font.eo.c"
25#include "interfaces/efl_text_style.eo.c" 25#include "interfaces/efl_text_style.eo.c"
26#include "interfaces/efl_text_format.eo.c" 26#include "interfaces/efl_text_format.eo.c"
27#include "interfaces/efl_text_annotate.eo.c"
28#include "interfaces/efl_text_markup.eo.c" 27#include "interfaces/efl_text_markup.eo.c"
29 28
30#include "interfaces/efl_gfx_entity.eo.c" 29#include "interfaces/efl_gfx_entity.eo.c"
diff --git a/src/lib/efl/interfaces/efl_text_annotate.eo b/src/lib/efl/interfaces/efl_text_annotate.eo
deleted file mode 100644
index 5ca1df8..0000000
--- a/src/lib/efl/interfaces/efl_text_annotate.eo
+++ /dev/null
@@ -1,137 +0,0 @@
1import efl_text_types;
2
3interface @beta Efl.Text_Annotate {
4 [[Cursor API
5 ]]
6 c_prefix: efl_text;
7 methods {
8 // Annotation
9 @property annotation {
10 [[A new format for $annotation.
11
12 This will replace the format applied by $annotation with $format.
13 Assumes that $annotation is a handle for an existing annotation,
14 i.e. one that was added using @.annotation_insert to this object.
15 Otherwise, this will fail and return $false.
16 ]]
17 set {
18 return: bool; [[$true on success, $false otherwise.]]
19 }
20 get {
21 }
22 keys {
23 annotation: ptr(Efl.Text_Annotate_Annotation); [[Given annotation]]
24 }
25 values {
26 format: string; [[The new format for the given annotation]]
27 }
28 }
29 range_annotations_get @const {
30 [[Returns an iterator of all the handles in a range.
31 ]]
32 params {
33 @in start: ptr(const(Efl.Text_Cursor_Handle)); [[Start of range]]
34 @in end: ptr(const(Efl.Text_Cursor_Handle)); [[End of range]]
35 }
36 return: iterator<ptr(Efl.Text_Annotate_Annotation)> @move; [[Handle of the Annotation]]
37 }
38 annotation_insert {
39 [[Inserts an annotation format in a specified range [$start, $end - 1].
40
41 The $format will be applied to the given range, and the $annotation
42 handle will be returned for further handling.
43 ]]
44 params {
45 @in start: ptr(Efl.Text_Cursor_Handle); [[Start of range]]
46 @in end: ptr(Efl.Text_Cursor_Handle); [[End of range]]
47 @in format: string; [[Annotation format]]
48 }
49 return: ptr(Efl.Text_Annotate_Annotation); [[Handle of inserted annotation]]
50 }
51 annotation_del {
52 [[Deletes given annotation.
53
54 All formats applied by $annotation will be removed and it will be
55 deleted.
56 ]]
57 params {
58 @in annotation: ptr(Efl.Text_Annotate_Annotation); [[Annotation to be
59 removed]]
60 }
61 return: bool; [[$true on success, $false otherwise.]]
62 }
63 annotation_positions_get {
64 [[Sets given cursors to the start and end positions of the annotation.
65
66 The cursors $start and $end will be set to the start and end
67 positions of the given annotation $annotation.
68 ]]
69 params {
70 @in annotation: ptr(const(Efl.Text_Annotate_Annotation)); [[Annotation
71 handle to query]]
72 @in start: ptr(Efl.Text_Cursor_Handle); [[Cursor to be set to the start
73 position of the annotation in the text]]
74 @in end: ptr(Efl.Text_Cursor_Handle); [[Cursor to be set to the end
75 position of the annotation in the text]]
76 }
77 }
78 annotation_is_item {
79 [[Whether this is an "item" type of annotation. Should be used before
80 querying the annotation's geometry, as only "item" annotations have
81 a geometry.
82
83 see @.cursor_item_insert
84 see @.item_geometry_get
85 ]]
86 params {
87 annotation: ptr(Efl.Text_Annotate_Annotation); [[Given annotation]]
88 }
89 return: bool; [[$true if given annotation is an object item, $false otherwise]]
90 }
91 item_geometry_get {
92 [[Queries a given object item for its geometry.
93
94 Note that the provided annotation should be an object item type.
95 ]]
96 params {
97 @in an: ptr(const(Efl.Text_Annotate_Annotation)); [[Given annotation to query]]
98 @out x: int; [[X coordinate of the annotation]]
99 @out y: int; [[Y coordinate of the annotation]]
100 @out w: int; [[Width of the annotation]]
101 @out h: int; [[Height of the annotation]]
102 }
103 return: bool; [[$true if given annotation is an object item, $false otherwise]]
104 }
105 // Cursor
106 @property cursor_item_annotation {
107 [[The object-item annotation at the cursor's position.]]
108 get {
109 }
110 values {
111 annotation: ptr(Efl.Text_Annotate_Annotation); [[Annotation]]
112 }
113 keys {
114 cur: ptr(Efl.Text_Cursor_Handle); [[Cursor object]]
115 }
116 }
117 cursor_item_insert {
118 [[Inserts a object item at specified position.
119
120 This adds a placeholder to be queried by higher-level code,
121 which in turn place graphics on top of it. It essentially places an
122 OBJECT REPLACEMENT CHARACTER and set a special annotation to it.
123 ]]
124 params {
125 cur: ptr(Efl.Text_Cursor_Handle); [[Cursor object]]
126 @in item: string; [[Item key to be used in higher-up
127 code to query and decided what image, emoticon
128 etc. to embed.]]
129 @in format: string; [[Size format of the inserted item.
130 This hints how to size the item in the text.]]
131 }
132 return: ptr(Efl.Text_Annotate_Annotation); [[The annotation handle of the
133 inserted item.]]
134 }
135 }
136}
137
diff --git a/src/lib/efl/interfaces/efl_text_types.eot b/src/lib/efl/interfaces/efl_text_types.eot
index 64eb393..159975e 100644
--- a/src/lib/efl/interfaces/efl_text_types.eot
+++ b/src/lib/efl/interfaces/efl_text_types.eot
@@ -22,6 +22,4 @@ struct @beta Efl.Ui.Text_Change_Info {
22 merge: bool; [[$true if can be merged with the previous one. Used for example with insertion when something is already selected]] 22 merge: bool; [[$true if can be merged with the previous one. Used for example with insertion when something is already selected]]
23} 23}
24 24
25type @extern @beta Efl.Text_Annotate_Annotation: __undefined_type; [[EFL text annotations data structure]] 25struct @extern @beta Efl.Text_Attribute_Handle; [[EFL text annotations data structure]] \ No newline at end of file
26
27struct @beta Efl.Text_Cursor_Handle; [[Opaque handle for Text cursors.]]
diff --git a/src/lib/efl/interfaces/meson.build b/src/lib/efl/interfaces/meson.build
index f45e743..a823e01 100644
--- a/src/lib/efl/interfaces/meson.build
+++ b/src/lib/efl/interfaces/meson.build
@@ -44,7 +44,6 @@ pub_eo_files = [
44 'efl_text_font.eo', 44 'efl_text_font.eo',
45 'efl_text_style.eo', 45 'efl_text_style.eo',
46 'efl_text_format.eo', 46 'efl_text_format.eo',
47 'efl_text_annotate.eo',
48 'efl_text_markup.eo', 47 'efl_text_markup.eo',
49 'efl_text_markup_util.eo', 48 'efl_text_markup_util.eo',
50 'efl_gfx_stack.eo', 49 'efl_gfx_stack.eo',
diff --git a/src/lib/elementary/efl_ui_internal_text_interactive.c b/src/lib/elementary/efl_ui_internal_text_interactive.c
index 5f623f8..608f672 100644
--- a/src/lib/elementary/efl_ui_internal_text_interactive.c
+++ b/src/lib/elementary/efl_ui_internal_text_interactive.c
@@ -4,6 +4,7 @@
4 4
5#include "elm_priv.h" 5#include "elm_priv.h"
6#include "efl_ui_internal_text_interactive.h" 6#include "efl_ui_internal_text_interactive.h"
7#include "efl_canvas_text_internal.h"
7 8
8#define MY_CLASS EFL_UI_INTERNAL_TEXT_INTERACTIVE_CLASS 9#define MY_CLASS EFL_UI_INTERNAL_TEXT_INTERACTIVE_CLASS
9 10
diff --git a/src/lib/elementary/efl_ui_text.c b/src/lib/elementary/efl_ui_text.c
index e57fc9c..73f010e 100644
--- a/src/lib/elementary/efl_ui_text.c
+++ b/src/lib/elementary/efl_ui_text.c
@@ -153,7 +153,7 @@ struct _Anchor
153{ 153{
154 Eo *obj; 154 Eo *obj;
155 char *name; 155 char *name;
156 Efl_Text_Annotate_Annotation *annotation; 156 Efl_Text_Attribute_Handle *annotation;
157 Eina_List *rects; 157 Eina_List *rects;
158 int gen; 158 int gen;
159 Eina_Bool item : 1; 159 Eina_Bool item : 1;
@@ -3180,13 +3180,12 @@ _efl_ui_text_efl_access_text_range_extents_get(const Eo *obj, Efl_Ui_Text_Data *
3180} 3180}
3181 3181
3182static Efl_Access_Text_Attribute* 3182static Efl_Access_Text_Attribute*
3183_textblock_node_format_to_atspi_text_attr(const Eo *obj, 3183_textblock_node_format_to_atspi_text_attr(Efl_Text_Attribute_Handle *annotation)
3184 Efl_Text_Annotate_Annotation *annotation)
3185{ 3184{
3186 Efl_Access_Text_Attribute *ret; 3185 Efl_Access_Text_Attribute *ret;
3187 const char *txt; 3186 const char *txt;
3188 3187
3189 txt = efl_text_annotation_get(obj, annotation); 3188 txt = efl_text_attribute_factory_attribute_get(annotation);
3190 if (!txt) return NULL; 3189 if (!txt) return NULL;
3191 3190
3192 ret = calloc(1, sizeof(Efl_Access_Text_Attribute)); 3191 ret = calloc(1, sizeof(Efl_Access_Text_Attribute));
@@ -3202,34 +3201,35 @@ _textblock_node_format_to_atspi_text_attr(const Eo *obj,
3202EOLIAN static Eina_Bool 3201EOLIAN static Eina_Bool
3203_efl_ui_text_efl_access_text_attribute_get(const Eo *obj, Efl_Ui_Text_Data *_pd EINA_UNUSED, const char *attr_name EINA_UNUSED, int *start_offset, int *end_offset, char **value) 3202_efl_ui_text_efl_access_text_attribute_get(const Eo *obj, Efl_Ui_Text_Data *_pd EINA_UNUSED, const char *attr_name EINA_UNUSED, int *start_offset, int *end_offset, char **value)
3204{ 3203{
3205 Evas_Textblock_Cursor *cur1, *cur2; 3204 Efl_Text_Cursor *cur1, *cur2;
3206 Efl_Access_Text_Attribute *attr; 3205 Efl_Access_Text_Attribute *attr;
3207 Eina_Iterator *annotations; 3206 Eina_Iterator *annotations;
3208 Efl_Text_Annotate_Annotation *an; 3207 Efl_Text_Attribute_Handle *an;
3209 3208
3210 cur1 = evas_object_textblock_cursor_new(obj); 3209 Eo *mobj = (Eo *)obj;
3210 cur1 = efl_ui_text_cursor_create(mobj);
3211 if (!cur1) return EINA_FALSE; 3211 if (!cur1) return EINA_FALSE;
3212 3212
3213 cur2 = evas_object_textblock_cursor_new(obj); 3213 cur2 = efl_ui_text_cursor_create(mobj);
3214 if (!cur2) 3214 if (!cur2)
3215 { 3215 {
3216 evas_textblock_cursor_free(cur1); 3216 efl_del(cur1);
3217 return EINA_FALSE; 3217 return EINA_FALSE;
3218 } 3218 }
3219 3219
3220 evas_textblock_cursor_pos_set(cur1, *start_offset); 3220 efl_text_cursor_position_set(cur1, *start_offset);
3221 evas_textblock_cursor_pos_set(cur2, *end_offset); 3221 efl_text_cursor_position_set(cur2, *end_offset);
3222 3222
3223 annotations = efl_text_range_annotations_get(obj, cur1, cur2); 3223 annotations = efl_text_attribute_factory_range_attributes_get(cur1, cur2);
3224 3224
3225 evas_textblock_cursor_free(cur1); 3225 efl_del(cur1);
3226 evas_textblock_cursor_free(cur2); 3226 efl_del(cur2);
3227 3227
3228 if (!annotations) return EINA_FALSE; 3228 if (!annotations) return EINA_FALSE;
3229 3229
3230 EINA_ITERATOR_FOREACH(annotations, an) 3230 EINA_ITERATOR_FOREACH(annotations, an)
3231 { 3231 {
3232 attr = _textblock_node_format_to_atspi_text_attr(obj, an); 3232 attr = _textblock_node_format_to_atspi_text_attr(an);
3233 if (!attr) continue; 3233 if (!attr) continue;
3234 if (!strcmp(attr->name, attr_name)) 3234 if (!strcmp(attr->name, attr_name))
3235 { 3235 {
@@ -3247,35 +3247,35 @@ _efl_ui_text_efl_access_text_attribute_get(const Eo *obj, Efl_Ui_Text_Data *_pd
3247EOLIAN static Eina_List* 3247EOLIAN static Eina_List*
3248_efl_ui_text_efl_access_text_text_attributes_get(const Eo *obj, Efl_Ui_Text_Data *pd EINA_UNUSED, int *start_offset, int *end_offset) 3248_efl_ui_text_efl_access_text_text_attributes_get(const Eo *obj, Efl_Ui_Text_Data *pd EINA_UNUSED, int *start_offset, int *end_offset)
3249{ 3249{
3250 Evas_Textblock_Cursor *cur1, *cur2; 3250 Efl_Text_Cursor *cur1, *cur2;
3251 Eina_List *ret = NULL; 3251 Eina_List *ret = NULL;
3252 Efl_Access_Text_Attribute *attr; 3252 Efl_Access_Text_Attribute *attr;
3253 Eina_Iterator *annotations; 3253 Eina_Iterator *annotations;
3254 Efl_Text_Annotate_Annotation *an; 3254 Efl_Text_Attribute_Handle *an;
3255 3255 Eo *mobj = (Eo *)obj;
3256 cur1 = evas_object_textblock_cursor_new(obj); 3256 cur1 = efl_ui_text_cursor_create(mobj);
3257 if (!cur1) return NULL; 3257 if (!cur1) return NULL;
3258 3258
3259 cur2 = evas_object_textblock_cursor_new(obj); 3259 cur2 = efl_ui_text_cursor_create(mobj);
3260 if (!cur2) 3260 if (!cur2)
3261 { 3261 {
3262 evas_textblock_cursor_free(cur1); 3262 efl_del(cur1);
3263 return NULL; 3263 return NULL;
3264 } 3264 }
3265 3265
3266 evas_textblock_cursor_pos_set(cur1, *start_offset); 3266 efl_text_cursor_position_set(cur1, *start_offset);
3267 evas_textblock_cursor_pos_set(cur2, *end_offset); 3267 efl_text_cursor_position_set(cur2, *end_offset);
3268 3268
3269 annotations = efl_text_range_annotations_get(obj, cur1, cur2); 3269 annotations = efl_text_attribute_factory_range_attributes_get(cur1, cur2);
3270 3270
3271 evas_textblock_cursor_free(cur1); 3271 efl_del(cur1);
3272 evas_textblock_cursor_free(cur2); 3272 efl_del(cur2);
3273 3273
3274 if (!annotations) return NULL; 3274 if (!annotations) return NULL;
3275 3275
3276 EINA_ITERATOR_FOREACH(annotations, an) 3276 EINA_ITERATOR_FOREACH(annotations, an)
3277 { 3277 {
3278 attr = _textblock_node_format_to_atspi_text_attr(obj, an); 3278 attr = _textblock_node_format_to_atspi_text_attr(an);
3279 if (!attr) continue; 3279 if (!attr) continue;
3280 ret = eina_list_append(ret, attr); 3280 ret = eina_list_append(ret, attr);
3281 } 3281 }
@@ -3291,7 +3291,7 @@ _efl_ui_text_efl_access_text_default_attributes_get(const Eo *obj, Efl_Ui_Text_D
3291 Efl_Access_Text_Attribute *attr; 3291 Efl_Access_Text_Attribute *attr;
3292 Efl_Text_Cursor *start, *end; 3292 Efl_Text_Cursor *start, *end;
3293 Eina_Iterator *annotations; 3293 Eina_Iterator *annotations;
3294 Efl_Text_Annotate_Annotation *an; 3294 Efl_Text_Attribute_Handle *an;
3295 3295
3296 /* Retrieve all annotations in the text. */ 3296 /* Retrieve all annotations in the text. */
3297 Eo *mobj = (Eo *)obj; /* XXX const */ 3297 Eo *mobj = (Eo *)obj; /* XXX const */
@@ -3301,11 +3301,11 @@ _efl_ui_text_efl_access_text_default_attributes_get(const Eo *obj, Efl_Ui_Text_D
3301 efl_text_cursor_move(start, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_FIRST); 3301 efl_text_cursor_move(start, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_FIRST);
3302 efl_text_cursor_move(end, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_LAST); 3302 efl_text_cursor_move(end, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_LAST);
3303 3303
3304 annotations = efl_text_range_annotations_get(obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end)); 3304 annotations = efl_text_attribute_factory_range_attributes_get(start, end);
3305 3305
3306 EINA_ITERATOR_FOREACH(annotations, an) 3306 EINA_ITERATOR_FOREACH(annotations, an)
3307 { 3307 {
3308 attr = _textblock_node_format_to_atspi_text_attr(obj, an); 3308 attr = _textblock_node_format_to_atspi_text_attr(an);
3309 if (!attr) continue; 3309 if (!attr) continue;
3310 ret = eina_list_append(ret, attr); 3310 ret = eina_list_append(ret, attr);
3311 } 3311 }
@@ -3659,20 +3659,20 @@ _anchor_format_parse(const char *item)
3659} 3659}
3660 3660
3661static Anchor * 3661static Anchor *
3662_anchor_get(Eo *obj, Efl_Ui_Text_Data *sd, Efl_Text_Annotate_Annotation *an) 3662_anchor_get(Eo *obj, Efl_Ui_Text_Data *sd, Efl_Text_Attribute_Handle *an)
3663{ 3663{
3664 Anchor *anc; 3664 Anchor *anc;
3665 Eina_List *i; 3665 Eina_List *i;
3666 const char *str; 3666 const char *str;
3667 3667
3668 str = efl_text_annotation_get(obj, an); 3668 str = efl_text_attribute_factory_attribute_get(an);
3669 3669
3670 EINA_LIST_FOREACH(sd->anchors, i, anc) 3670 EINA_LIST_FOREACH(sd->anchors, i, anc)
3671 { 3671 {
3672 if (anc->annotation == an) break; 3672 if (anc->annotation == an) break;
3673 } 3673 }
3674 3674
3675 if (!anc && (efl_text_annotation_is_item(obj, an) || !strncmp(str, "a ", 2))) 3675 if (!anc && (efl_text_attribute_factory_attribute_is_item(an) || !strncmp(str, "a ", 2)))
3676 { 3676 {
3677 const char *p; 3677 const char *p;
3678 3678
@@ -3681,7 +3681,7 @@ _anchor_get(Eo *obj, Efl_Ui_Text_Data *sd, Efl_Text_Annotate_Annotation *an)
3681 { 3681 {
3682 anc->obj = obj; 3682 anc->obj = obj;
3683 anc->annotation = an; 3683 anc->annotation = an;
3684 anc->item = efl_text_annotation_is_item(obj, an); 3684 anc->item = efl_text_attribute_factory_attribute_is_item(an);
3685 p = strstr(str, "href="); 3685 p = strstr(str, "href=");
3686 if (p) 3686 if (p)
3687 { 3687 {
@@ -3705,7 +3705,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
3705 Eina_Iterator *it; 3705 Eina_Iterator *it;
3706 Eina_Position2D off; 3706 Eina_Position2D off;
3707 Efl_Text_Cursor *start, *end; 3707 Efl_Text_Cursor *start, *end;
3708 Efl_Text_Annotate_Annotation *an; 3708 Efl_Text_Attribute_Handle *an;
3709 Eina_List *i, *ii; 3709 Eina_List *i, *ii;
3710 Anchor *anc; 3710 Anchor *anc;
3711 3711
@@ -3723,7 +3723,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
3723 efl_text_cursor_move(start, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_FIRST); 3723 efl_text_cursor_move(start, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_FIRST);
3724 efl_text_cursor_move(end, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_LAST); 3724 efl_text_cursor_move(end, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_LAST);
3725 3725
3726 it = efl_text_range_annotations_get(obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end)); 3726 it = efl_text_attribute_factory_range_attributes_get(start, end);
3727 efl_del(start); 3727 efl_del(start);
3728 efl_del(end); 3728 efl_del(end);
3729 3729
@@ -3765,8 +3765,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
3765 } 3765 }
3766 3766
3767 rect = eina_list_data_get(anc->rects); 3767 rect = eina_list_data_get(anc->rects);
3768 efl_text_item_geometry_get(sd->text_obj, 3768 efl_text_attribute_factory_item_geometry_get(anc->annotation, &cx, &cy, &cw, &ch);
3769 anc->annotation, &cx, &cy, &cw, &ch);
3770 efl_gfx_entity_size_set(rect->obj, EINA_SIZE2D(cw, ch)); 3769 efl_gfx_entity_size_set(rect->obj, EINA_SIZE2D(cw, ch));
3771 efl_gfx_entity_position_set(rect->obj, 3770 efl_gfx_entity_position_set(rect->obj,
3772 EINA_POSITION2D(off.x + cx, off.y + cy)); 3771 EINA_POSITION2D(off.x + cx, off.y + cy));
@@ -3780,8 +3779,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
3780 size_t count; 3779 size_t count;
3781 start = efl_ui_text_cursor_create(obj); 3780 start = efl_ui_text_cursor_create(obj);
3782 end = efl_ui_text_cursor_create(obj); 3781 end = efl_ui_text_cursor_create(obj);
3783 efl_text_annotation_positions_get(obj, anc->annotation, 3782 efl_text_attribute_factory_attribute_cursors_get(anc->annotation, start, end);
3784 efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end));
3785 3783
3786 range = efl_text_cursor_range_geometry_get(start, end); 3784 range = efl_text_cursor_range_geometry_get(start, end);
3787 count = eina_list_count(eina_iterator_container_get(range)); 3785 count = eina_list_count(eina_iterator_container_get(range));
diff --git a/src/lib/evas/Efl_Canvas.h b/src/lib/evas/Efl_Canvas.h
index a82d6a3..ed30047 100644
--- a/src/lib/evas/Efl_Canvas.h
+++ b/src/lib/evas/Efl_Canvas.h
@@ -84,6 +84,7 @@ extern "C" {
84*/ 84*/
85#include <canvas/efl_canvas_snapshot.eo.h> 85#include <canvas/efl_canvas_snapshot.eo.h>
86#include <canvas/efl_text_cursor.eo.h> 86#include <canvas/efl_text_cursor.eo.h>
87#include <canvas/efl_text_attribute_factory.eo.h>
87#include <canvas/efl_canvas_text.eo.h> 88#include <canvas/efl_canvas_text.eo.h>
88#include <canvas/efl_canvas_text_factory.eo.h> 89#include <canvas/efl_canvas_text_factory.eo.h>
89#include <canvas/efl_canvas_vg_node.eo.h> 90#include <canvas/efl_canvas_vg_node.eo.h>
diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h
index 7b5db77..56971d0 100644
--- a/src/lib/evas/Evas_Eo.h
+++ b/src/lib/evas/Evas_Eo.h
@@ -155,6 +155,7 @@ struct _Efl_Canvas_Object_Animation_Event
155 * @{ 155 * @{
156 */ 156 */
157#include "canvas/efl_text_cursor.eo.h" 157#include "canvas/efl_text_cursor.eo.h"
158#include "canvas/efl_text_attribute_factory.eo.h"
158#include "canvas/efl_canvas_text.eo.h" 159#include "canvas/efl_canvas_text.eo.h"
159#include "canvas/efl_canvas_text_factory.eo.h" 160#include "canvas/efl_canvas_text_factory.eo.h"
160/** 161/**
diff --git a/src/lib/evas/Evas_Internal.h b/src/lib/evas/Evas_Internal.h
index d631cdc..0fa833c 100644
--- a/src/lib/evas/Evas_Internal.h
+++ b/src/lib/evas/Evas_Internal.h
@@ -318,6 +318,17 @@ EWAPI extern const Efl_Event_Description _EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED
318 */ 318 */
319EAPI Eina_Bool evas_textblock_cursor_at_cluster_as_single_glyph(Evas_Textblock_Cursor *cur,Eina_Bool forward); 319EAPI Eina_Bool evas_textblock_cursor_at_cluster_as_single_glyph(Evas_Textblock_Cursor *cur,Eina_Bool forward);
320 320
321
322
323
324/*Attribute Factory Internal function*/
325EAPI const char * efl_text_attribute_factory_attribute_get(Efl_Text_Attribute_Handle *annotation);
326EAPI Eina_Iterator * efl_text_attribute_factory_range_attributes_get(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end);
327EAPI void efl_text_attribute_factory_attribute_cursors_get(const Efl_Text_Attribute_Handle *handle, Efl_Text_Cursor *start, Efl_Text_Cursor *end);
328EAPI void efl_text_attribute_factory_remove(Efl_Text_Attribute_Handle *annotation);
329EAPI Eina_Bool efl_text_attribute_factory_attribute_is_item(Efl_Text_Attribute_Handle *annotation);
330EAPI Eina_Bool efl_text_attribute_factory_item_geometry_get(const Efl_Text_Attribute_Handle *annotation, int *x, int *y, int *w, int *h);
331
321#ifdef __cplusplus 332#ifdef __cplusplus
322} 333}
323#endif 334#endif
diff --git a/src/lib/evas/canvas/efl_canvas_text.eo b/src/lib/evas/canvas/efl_canvas_text.eo
index 1e53fdb..10c43c7 100644
--- a/src/lib/evas/canvas/efl_canvas_text.eo
+++ b/src/lib/evas/canvas/efl_canvas_text.eo
@@ -3,7 +3,7 @@ import efl_text_types;
3class @beta Efl.Canvas.Text extends Efl.Canvas.Object implements Efl.Text, 3class @beta Efl.Canvas.Text extends Efl.Canvas.Object implements Efl.Text,
4 Efl.Canvas.Filter.Internal, Efl.Text_Font, 4 Efl.Canvas.Filter.Internal, Efl.Text_Font,
5 Efl.Text_Style, Efl.Text_Format, 5 Efl.Text_Style, Efl.Text_Format,
6 Efl.Text_Annotate, Efl.Text_Markup, Efl.Ui.I18n 6 Efl.Text_Markup, Efl.Ui.I18n
7{ 7{
8 [[Efl canvas text class]] 8 [[Efl canvas text class]]
9 methods { 9 methods {
@@ -236,15 +236,6 @@ class @beta Efl.Canvas.Text extends Efl.Canvas.Object implements Efl.Text,
236 Efl.Text_Format.tabstops { get; set; } 236 Efl.Text_Format.tabstops { get; set; }
237 Efl.Text_Format.password { get; set; } 237 Efl.Text_Format.password { get; set; }
238 Efl.Text_Format.replacement_char { get; set; } 238 Efl.Text_Format.replacement_char { get; set; }
239 Efl.Text_Annotate.annotation { set; get; }
240 Efl.Text_Annotate.range_annotations_get;
241 Efl.Text_Annotate.annotation_insert;
242 Efl.Text_Annotate.annotation_del;
243 Efl.Text_Annotate.annotation_is_item;
244 Efl.Text_Annotate.item_geometry_get;
245 Efl.Text_Annotate.annotation_positions_get;
246 Efl.Text_Annotate.cursor_item_annotation { get; }
247 Efl.Text_Annotate.cursor_item_insert;
248 Efl.Text_Markup.markup { set; get; } 239 Efl.Text_Markup.markup { set; get; }
249 Efl.Gfx.Entity.scale { set; } 240 Efl.Gfx.Entity.scale { set; }
250 } 241 }
diff --git a/src/lib/evas/canvas/efl_canvas_text_internal.h b/src/lib/evas/canvas/efl_canvas_text_internal.h
index 64659ec..9871008 100644
--- a/src/lib/evas/canvas/efl_canvas_text_internal.h
+++ b/src/lib/evas/canvas/efl_canvas_text_internal.h
@@ -83,10 +83,10 @@ typedef struct _Evas_Object_Textblock_Format Evas_Object_Textblock_Format;
83typedef struct _Evas_Textblock_Selection_Iterator Evas_Textblock_Selection_Iterator; 83typedef struct _Evas_Textblock_Selection_Iterator Evas_Textblock_Selection_Iterator;
84/** 84/**
85 * @internal 85 * @internal
86 * @typedef Efl_Text_Annotate_Annotation_Iterator 86 * @typedef Efl_Text_Attribute_Handle_Iterator
87 * A textblock annotation iterator. 87 * A textblock annotation iterator.
88 */ 88 */
89typedef struct _Efl_Text_Annotate_Annotation_Iterator Efl_Text_Annotate_Annotation_Iterator; 89typedef struct _Efl_Text_Attribute_Handle_Iterator Efl_Text_Attribute_Handle_Iterator;
90/** 90/**
91 * @internal 91 * @internal
92 * @typedef Efl_Canvas_Text_Filter 92 * @typedef Efl_Canvas_Text_Filter
@@ -143,7 +143,7 @@ struct _Evas_Textblock_Node_Format
143 const char *format; /**< Cached, parsed and translated version of orig_format. */ 143 const char *format; /**< Cached, parsed and translated version of orig_format. */
144 const char *orig_format; /**< Original format information. */ 144 const char *orig_format; /**< Original format information. */
145 Evas_Object_Textblock_Node_Text *text_node; /**< The text node it's pointing to. */ 145 Evas_Object_Textblock_Node_Text *text_node; /**< The text node it's pointing to. */
146 Efl_Text_Annotate_Annotation *annotation; /**< Pointer to this node's annotation handle (if exists). */ 146 Efl_Text_Attribute_Handle *annotation; /**< Pointer to this node's annotation handle (if exists). */
147 size_t offset; /**< Offset from the last format node of the same text. */ 147 size_t offset; /**< Offset from the last format node of the same text. */
148 struct { 148 struct {
149 unsigned char l, r, t, b; 149 unsigned char l, r, t, b;
@@ -166,8 +166,17 @@ struct _Efl_Text_Cursor_Handle
166 Eina_Bool changed : 1; 166 Eina_Bool changed : 1;
167}; 167};
168 168
169struct _Efl_Text_Attribute_Handle
170{
171 EINA_INLIST;
172 Evas_Object *obj;
173 Evas_Object_Textblock_Node_Format *start_node, *end_node;
174 Eina_Bool is_item : 1; /**< indicates it is an item/object placeholder */
175};
176
169void evas_textblock_cursor_line_jump_by(Efl_Text_Cursor_Handle *cur, int by); 177void evas_textblock_cursor_line_jump_by(Efl_Text_Cursor_Handle *cur, int by);
170int _cursor_text_append(Efl_Text_Cursor_Handle *cur, const char *text); 178int _cursor_text_append(Efl_Text_Cursor_Handle *cur, const char *text);
179void evas_textblock_async_block(Evas_Object *eo_object);
171 180
172 181
173// Used in Efl.Text.Cursor, where multible objects can have same handle. 182// Used in Efl.Text.Cursor, where multible objects can have same handle.
@@ -177,6 +186,76 @@ evas_textblock_cursor_ref(Efl_Text_Cursor_Handle *cursor, Eo * cursor_obj);
177// Used in Efl.Text.Cursor, where multible objects can have same handle. 186// Used in Efl.Text.Cursor, where multible objects can have same handle.
178void 187void
179evas_textblock_cursor_unref(Efl_Text_Cursor_Handle *cursor, Eo * cursor_obj); 188evas_textblock_cursor_unref(Efl_Text_Cursor_Handle *cursor, Eo * cursor_obj);
189void _evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb);
190
191/*Annoation Functions*/
192/**
193 * @internal
194 * Returns the value of the current data of list node,
195 * and goes to the next list node.
196 *
197 * @param it the iterator.
198 * @param data the data of the current list node.
199 * @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
200 */
201Eina_Bool
202_evas_textblock_annotation_iterator_next(Efl_Text_Attribute_Handle_Iterator *it, void **data);
203
204/**
205 * @internal
206 * Frees the annotation iterator.
207 * @param it the iterator to free
208 * @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
209 */
210void
211_evas_textblock_annotation_iterator_free(Efl_Text_Attribute_Handle_Iterator *it);
212
213
214/**
215 * @internal
216 * Creates newly allocated iterator associated to a list.
217 * @param list The list.
218 * @return If the memory cannot be allocated, NULL is returned.
219 * Otherwise, a valid iterator is returned.
220 */
221Eina_Iterator *
222_evas_textblock_annotation_iterator_new(Eina_List *list);
223
224
225
226void
227_textblock_cursor_pos_at_fnode_set(Efl_Text_Cursor_Handle *cur,
228 Evas_Object_Textblock_Node_Format *fnode);
229
230
231Eina_Bool
232_evas_textblock_annotations_set(Evas_Object *eo_obj,
233 Efl_Text_Attribute_Handle *an,
234 Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
235 const char *format, Eina_Bool is_item);
236
237void
238_evas_textblock_annotation_remove(Evas_Object *eo_obj, Efl_Canvas_Text_Data *o,
239 Efl_Text_Attribute_Handle *an, Eina_Bool remove_nodes, Eina_Bool invalidate);
240
241void
242_evas_textblock_annotations_clear(const Evas_Object *eo_obj);
243
244
245Efl_Text_Attribute_Handle *
246_evas_textblock_annotations_insert(Eo *eo_obj,
247 Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
248 const char *format, Eina_Bool is_item);
249
250
251Eina_Inlist *
252_evas_textblock_annotations_get(Evas_Object *o);
253
254void
255_evas_textblock_annotations_node_format_remove(Evas_Object *o, Evas_Object_Textblock_Node_Format *n, int visual_adjustment);
256
257void
258_evas_textblock_relayout_if_needed(Evas_Object *o);
180 259
181#ifdef EAPI 260#ifdef EAPI
182# undef EAPI 261# undef EAPI
@@ -213,7 +292,24 @@ evas_textblock_cursor_unref(Efl_Text_Cursor_Handle *cursor, Eo * cursor_obj);
213 */ 292 */
214EAPI void efl_text_cursor_text_object_set(Eo *cursor, Eo *canvas_text_obj, Eo *text_obj); 293EAPI void efl_text_cursor_text_object_set(Eo *cursor, Eo *canvas_text_obj, Eo *text_obj);
215 294
295
296/**
297 * Internally sets cursor handle(legacy textblock cursor) into cursor object.
298 *
299 * @param obj the cursor object.
300 * @param handle the text cursor handle.
301 */
302EAPI void efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Handle *handle);
303
304/**
305 * Internally gets cursor handle(legacy textblock cursor) from cursor object.
306 *
307 * @param obj the cursor object.
308 * @return the internal text cursor handle.
309 */
310EAPI Efl_Text_Cursor_Handle *efl_text_cursor_handle_get(const Eo *obj);
311
216#undef EAPI 312#undef EAPI
217#define EAPI 313#define EAPI
218 314
219#endif \ No newline at end of file 315#endif//#ifndef _EFL_CANVAS_TEXT_INTERNAL_H
diff --git a/src/lib/evas/canvas/efl_text_attribute_factory.c b/src/lib/evas/canvas/efl_text_attribute_factory.c
new file mode 100644
index 0000000..2e01ee8
--- /dev/null
+++ b/src/lib/evas/canvas/efl_text_attribute_factory.c
@@ -0,0 +1,133 @@
1//#define EFL_BETA_API_SUPPORT
2#include "evas_common_private.h"
3#include "evas_private.h"
4#include "efl_canvas_text_internal.h"
5#include "efl_text_cursor.eo.h"
6
7#define MY_CLASS EFL_TEXT_ATTRIBUTE_FACTORY_CLASS
8
9typedef struct
10{
11
12} Efl_Text_Attribute_Factory_Data;
13
14EOLIAN static void
15_efl_text_attribute_factory_attribute_insert(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end, const char *format)
16{
17 EINA_SAFETY_ON_TRUE_RETURN(!efl_text_cursor_handle_get(start) ||
18 !efl_text_cursor_handle_get(end) ||
19 efl_text_cursor_handle_get(start)->obj != efl_text_cursor_handle_get(end)->obj);
20
21 Eo *eo_obj= efl_text_cursor_handle_get(start)->obj;
22 evas_textblock_async_block(eo_obj);
23
24 _evas_textblock_annotations_insert(eo_obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end), format,
25 EINA_FALSE);
26 efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
27}
28
29EOLIAN static unsigned int
30_efl_text_attribute_factory_attribute_clear(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end)
31{
32 unsigned int ret = 0;
33 Eina_Iterator *annotations;
34 Efl_Text_Attribute_Handle *an;
35 annotations = efl_text_attribute_factory_range_attributes_get(start, end);
36
37 if (!annotations) return ret;
38
39 EINA_ITERATOR_FOREACH(annotations, an)
40 {
41 ret++;
42 efl_text_attribute_factory_remove(an);
43 }
44 eina_iterator_free(annotations);
45
46 return ret;
47}
48
49const char *
50efl_text_attribute_factory_attribute_get(Efl_Text_Attribute_Handle *annotation)
51{
52 EINA_SAFETY_ON_TRUE_RETURN_VAL(!annotation || !(annotation->obj), NULL);
53
54 return (annotation->start_node ? annotation->start_node->format : NULL);
55}
56
57Eina_Iterator *
58efl_text_attribute_factory_range_attributes_get(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end)
59{
60 Eina_List *lst = NULL;
61 Efl_Text_Attribute_Handle *it;
62
63 EINA_SAFETY_ON_TRUE_RETURN_VAL(!efl_text_cursor_handle_get(start) ||
64 !efl_text_cursor_handle_get(end) ||
65 efl_text_cursor_handle_get(start)->obj != efl_text_cursor_handle_get(end)->obj, NULL);
66
67 Eina_Inlist *annotations = _evas_textblock_annotations_get(efl_text_cursor_handle_get(start)->obj);
68
69 EINA_INLIST_FOREACH(annotations, it)
70 {
71 Efl_Text_Cursor_Handle start2, end2;
72 _evas_textblock_cursor_init(&start2, efl_text_cursor_handle_get(start)->obj);
73 _evas_textblock_cursor_init(&end2, efl_text_cursor_handle_get(start)->obj);
74
75 if (!it->start_node || !it->end_node) continue;
76 _textblock_cursor_pos_at_fnode_set(&start2, it->start_node);
77 _textblock_cursor_pos_at_fnode_set(&end2, it->end_node);
78 evas_textblock_cursor_char_prev(&end2);
79 if (!((evas_textblock_cursor_compare(&start2, efl_text_cursor_handle_get(end)) > 0) ||
80 (evas_textblock_cursor_compare(&end2, efl_text_cursor_handle_get(start)) < 0)))
81 {
82 lst = eina_list_append(lst, it);
83 }
84 }
85 return _evas_textblock_annotation_iterator_new(lst);
86}
87
88void
89efl_text_attribute_factory_attribute_cursors_get(const Efl_Text_Attribute_Handle *handle, Efl_Text_Cursor *start, Efl_Text_Cursor *end)
90{
91 EINA_SAFETY_ON_TRUE_RETURN (!handle || !(handle->obj));
92
93 efl_text_cursor_text_object_set(start, handle->obj, handle->obj);
94 efl_text_cursor_text_object_set(end, handle->obj, handle->obj);
95 _textblock_cursor_pos_at_fnode_set(efl_text_cursor_handle_get(start), handle->start_node);
96 _textblock_cursor_pos_at_fnode_set(efl_text_cursor_handle_get(end), handle->end_node);
97}
98
99void
100efl_text_attribute_factory_remove(Efl_Text_Attribute_Handle *annotation)
101{
102 EINA_SAFETY_ON_TRUE_RETURN (!annotation || !(annotation->obj));
103
104 evas_textblock_async_block(annotation->obj);
105 _evas_textblock_annotation_remove(annotation->obj, NULL, annotation, EINA_TRUE, EINA_TRUE);
106}
107
108Eina_Bool
109efl_text_attribute_factory_attribute_is_item(Efl_Text_Attribute_Handle *annotation)
110{
111 EINA_SAFETY_ON_TRUE_RETURN_VAL(!annotation || !(annotation->obj), EINA_FALSE);
112
113 return annotation->is_item;
114}
115
116Eina_Bool
117efl_text_attribute_factory_item_geometry_get(const Efl_Text_Attribute_Handle *annotation, int *x, int *y, int *w, int *h)
118{
119 EINA_SAFETY_ON_TRUE_RETURN_VAL(!annotation || !(annotation->obj), EINA_FALSE);
120
121 Efl_Text_Cursor_Handle cur;
122
123 Eo *eo_obj = annotation->obj;
124 Evas_Object_Protected_Data *obj_data = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
125 evas_object_async_block(obj_data);
126 _evas_textblock_relayout_if_needed(eo_obj);
127
128 _evas_textblock_cursor_init(&cur, eo_obj);
129 _textblock_cursor_pos_at_fnode_set(&cur, annotation->start_node);
130 return evas_textblock_cursor_format_item_geometry_get(&cur, x, y, w, h);
131}
132
133#include "efl_text_attribute_factory.eo.c"
diff --git a/src/lib/evas/canvas/efl_text_attribute_factory.eo b/src/lib/evas/canvas/efl_text_attribute_factory.eo
new file mode 100644
index 0000000..52bc871
--- /dev/null
+++ b/src/lib/evas/canvas/efl_text_attribute_factory.eo
@@ -0,0 +1,37 @@
1import efl_text_types;
2
3abstract @beta Efl.Text.Attribute.Factory extends Efl.Object {
4 [[Attribute factory API to manage text attributes.
5 Use it to insert and remove style attributes (font, size, color, ...) using @Efl.Text.Cursor on EFL Widgets.
6
7 Attributes can be assigned to character ranges, selected using two @Efl.Text.Cursor instances.
8 Cursor instances are already bound to a text object so there's no need to provide it to this class.
9 Style is specified using format strings as described in Efl.Canvas.Text.style_set.
10
11 There is no need to instantiate this class. Use directly the @.attribute_insert and @.attribute_clear static methods.]]
12 methods {
13 attribute_insert @static {
14 [[Inserts an attribute format in a specified range [$start, $end - 1].
15
16 The $format will be applied to the given range.
17 The passed cursors must belong to same textObject, else insertion will be ignored.
18 Passed format parameter uses same format as style in Efl.Canvas.Text.style_set.
19 ]]
20 params {
21 start: const(Efl.Text.Cursor); [[Start of range.]]
22 end: const(Efl.Text.Cursor); [[End of range.]]
23 format: string; [[Attribute format.]]
24 }
25 }
26
27 attribute_clear @static {
28 [[Clear(remove) attributes at specified range [$start, $end - 1].
29 ]]
30 params {
31 start: const(Efl.Text.Cursor); [[Start of range.]]
32 end: const(Efl.Text.Cursor); [[End of range.]]
33 }
34 return: uint; [[Number of removed attributes.]]
35 }
36 }
37}
diff --git a/src/lib/evas/canvas/efl_text_cursor.c b/src/lib/evas/canvas/efl_text_cursor.c
index cfa87d7..238c952 100644
--- a/src/lib/evas/canvas/efl_text_cursor.c
+++ b/src/lib/evas/canvas/efl_text_cursor.c
@@ -406,9 +406,10 @@ _efl_text_cursor_range_delete(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Data *pd, Efl
406 evas_textblock_cursor_range_delete(pd->handle, efl_text_cursor_handle_get(cur2)); 406 evas_textblock_cursor_range_delete(pd->handle, efl_text_cursor_handle_get(cur2));
407} 407}
408 408
409EOLIAN static void 409EAPI void
410_efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Data *pd, Efl_Text_Cursor_Handle *handle) 410efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Handle *handle)
411{ 411{
412 Efl_Text_Cursor_Data *pd = efl_data_scope_get(obj, MY_CLASS);
412 if (handle == pd->handle) 413 if (handle == pd->handle)
413 return; 414 return;
414 415
@@ -422,9 +423,10 @@ _efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Data *pd, Efl_Text_Cursor_H
422 } 423 }
423} 424}
424 425
425EOLIAN static Efl_Text_Cursor_Handle * 426EAPI Efl_Text_Cursor_Handle *
426_efl_text_cursor_handle_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Data *pd) 427efl_text_cursor_handle_get(const Eo *obj)
427{ 428{
429 Efl_Text_Cursor_Data *pd = efl_data_scope_get(obj, MY_CLASS);
428 return pd->handle; 430 return pd->handle;
429} 431}
430 432
diff --git a/src/lib/evas/canvas/efl_text_cursor.eo b/src/lib/evas/canvas/efl_text_cursor.eo
index 0485eb9..01c77fc 100644
--- a/src/lib/evas/canvas/efl_text_cursor.eo
+++ b/src/lib/evas/canvas/efl_text_cursor.eo
@@ -215,19 +215,6 @@ class @beta Efl.Text.Cursor extends Efl.Object implements Efl.Duplicate{
215 } 215 }
216 } 216 }
217 217
218 @property handle {
219 [[This method should rarely be used by users. It gives you a lightweight handle to a cursor.
220
221 You can either replace the handle to change the object this is working on, or get it for caching
222
223 The handle is freed when the object is freed if set, but otherwise it remains under the control of the caller.]]
224 set { }
225 get { }
226 values {
227 handle: Efl.Text_Cursor_Handle @by_ref; [[The handle of the cursor object.]]
228 }
229 }
230
231 @property text_object { 218 @property text_object {
232 [[The text object this cursor is associated with.]] 219 [[The text object this cursor is associated with.]]
233 get { } 220 get { }
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index e854d16..98cfc9f 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -419,13 +419,6 @@ typedef struct _User_Style_Entry
419 Evas_Textblock_Style *st; 419 Evas_Textblock_Style *st;
420 const char *key; 420 const char *key;
421} User_Style_Entry; 421} User_Style_Entry;
422struct _Efl_Text_Annotate_Annotation
423{
424 EINA_INLIST;
425 Evas_Object *obj;
426 Evas_Object_Textblock_Node_Format *start_node, *end_node;
427 Eina_Bool is_item : 1; /**< indicates it is an item/object placeholder */
428};
429 422
430#define _FMT(x) (o->default_format.format.x) 423#define _FMT(x) (o->default_format.format.x)
431#define _FMT_INFO(x) (o->default_format.info.x) 424#define _FMT_INFO(x) (o->default_format.info.x)
@@ -461,7 +454,7 @@ struct _Evas_Object_Textblock
461 Eina_List *anchors_item; 454 Eina_List *anchors_item;
462 Eina_List *obstacles; 455 Eina_List *obstacles;
463 Eina_List *hyphen_items; /* Hyphen items storage to free when clearing lines */ 456 Eina_List *hyphen_items; /* Hyphen items storage to free when clearing lines */
464 Efl_Text_Annotate_Annotation *annotations; /* All currently applied annotations on the text. */ 457 Efl_Text_Attribute_Handle *annotations; /* All currently applied annotations on the text. */
465 int last_w, last_h; 458 int last_w, last_h;
466 struct { 459 struct {
467 int l, r, t, b; 460 int l, r, t, b;
@@ -524,7 +517,7 @@ struct _Evas_Textblock_Selection_Iterator
524 Eina_List *current; /**< Current node in loop. */ 517 Eina_List *current; /**< Current node in loop. */
525}; 518};
526 519
527struct _Efl_Text_Annotate_Annotation_Iterator 520struct _Efl_Text_Attribute_Handle_Iterator
528{ 521{
529 Eina_Iterator iterator; /**< Eina Iterator. */ 522 Eina_Iterator iterator; /**< Eina Iterator. */
530 Eina_List *list; /**< Head of list. */ 523 Eina_List *list; /**< Head of list. */
@@ -604,12 +597,9 @@ static void _evas_textblock_changed(Efl_Canvas_Text_Data *o, Evas_Object *eo_obj
604static void _evas_textblock_invalidate_all(Efl_Canvas_Text_Data *o); 597static void _evas_textblock_invalidate_all(Efl_Canvas_Text_Data *o);
605static void _evas_textblock_cursors_update_offset(const Efl_Text_Cursor_Handle *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset); 598static void _evas_textblock_cursors_update_offset(const Efl_Text_Cursor_Handle *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset);
606static void _evas_textblock_cursors_set_node(Efl_Canvas_Text_Data *o, const Evas_Object_Textblock_Node_Text *n, Evas_Object_Textblock_Node_Text *new_node); 599static void _evas_textblock_cursors_set_node(Efl_Canvas_Text_Data *o, const Evas_Object_Textblock_Node_Text *n, Evas_Object_Textblock_Node_Text *new_node);
607static void _evas_textblock_annotations_clear(Efl_Canvas_Text_Data *o);
608static void _evas_textblock_annotation_remove(Efl_Canvas_Text_Data *o, Efl_Text_Annotate_Annotation *an, Eina_Bool remove_nodes);
609 600
610static Eina_Bool _evas_textblock_cursor_format_is_visible_get(const Efl_Text_Cursor_Handle *cur); 601static Eina_Bool _evas_textblock_cursor_format_is_visible_get(const Efl_Text_Cursor_Handle *cur);
611static void _evas_textblock_cursor_at_format_set(Efl_Text_Cursor_Handle *cur, const Evas_Object_Textblock_Node_Format *fmt); 602static void _evas_textblock_cursor_at_format_set(Efl_Text_Cursor_Handle *cur, const Evas_Object_Textblock_Node_Format *fmt);
612static void _evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb);
613static Evas_Filter_Program *_format_filter_program_get(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Format *fmt); 603static Evas_Filter_Program *_format_filter_program_get(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Format *fmt);
614static const char *_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Node_Format *fnode, const char *format, size_t format_len); 604static const char *_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Node_Format *fnode, const char *format, size_t format_len);
615#ifdef HAVE_HYPHEN 605#ifdef HAVE_HYPHEN
@@ -619,7 +609,6 @@ static const char *_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o
619 609
620static Eina_Bool _evas_textblock_cursor_format_append(Efl_Text_Cursor_Handle *cur, const char *format, Evas_Object_Textblock_Node_Format **_fnode, Eina_Bool is_item); 610static Eina_Bool _evas_textblock_cursor_format_append(Efl_Text_Cursor_Handle *cur, const char *format, Evas_Object_Textblock_Node_Format **_fnode, Eina_Bool is_item);
621EAPI Eina_Bool evas_textblock_cursor_eol_get(const Evas_Textblock_Cursor *cur); 611EAPI Eina_Bool evas_textblock_cursor_eol_get(const Evas_Textblock_Cursor *cur);
622static void _evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb);
623static Eina_Bool _evas_textblock_cursor_format_is_visible_get(const Efl_Text_Cursor_Handle *cur); 612static Eina_Bool _evas_textblock_cursor_format_is_visible_get(const Efl_Text_Cursor_Handle *cur);
624static void _find_layout_item_line_match(Evas_Object *eo_obj, Evas_Object_Textblock_Node_Text *n, size_t pos, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Item **itr); 613static void _find_layout_item_line_match(Evas_Object *eo_obj, Evas_Object_Textblock_Node_Text *n, size_t pos, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Item **itr);
625static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_at_pos_get(const Efl_Text_Cursor_Handle *cur); 614static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_at_pos_get(const Efl_Text_Cursor_Handle *cur);
@@ -803,7 +792,7 @@ _nodes_clear(const Evas_Object *eo_obj)
803 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); 792 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
804 793
805 /* First, clear all annotations that may have spawned format nodes. */ 794 /* First, clear all annotations that may have spawned format nodes. */
806 _evas_textblock_annotations_clear(o); 795 _evas_textblock_annotations_clear(eo_obj);
807 796
808 while (o->text_nodes) 797 while (o->text_nodes)
809 { 798 {
@@ -6966,6 +6955,13 @@ _relayout_if_needed(const Evas_Object *eo_obj, Efl_Canvas_Text_Data *o)
6966 return EINA_TRUE; 6955 return EINA_TRUE;
6967} 6956}
6968 6957
6958void
6959_evas_textblock_relayout_if_needed(Evas_Object *eo_obj)
6960{
6961 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
6962 _relayout_if_needed(eo_obj, o);
6963}
6964
6969/** 6965/**
6970 * @internal 6966 * @internal
6971 * Find the layout item and line that match the text node and position passed. 6967 * Find the layout item and line that match the text node and position passed.
@@ -8953,7 +8949,7 @@ _find_layout_item_match(const Efl_Text_Cursor_Handle *cur, Evas_Object_Textblock
8953 return previous_format; 8949 return previous_format;
8954} 8950}
8955 8951
8956static void 8952void
8957_evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb) 8953_evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb)
8958{ 8954{
8959 memset(cur, 0, sizeof(Efl_Text_Cursor_Handle)); 8955 memset(cur, 0, sizeof(Efl_Text_Cursor_Handle));
@@ -10082,7 +10078,7 @@ _evas_textblock_node_format_remove_matching(Efl_Canvas_Text_Data *o,
10082 if (_FORMAT_IS_CLOSER_OF( 10078 if (_FORMAT_IS_CLOSER_OF(
10083 fnode->orig_format, fstr + 1, fstr_len - 1)) 10079 fnode->orig_format, fstr + 1, fstr_len - 1))
10084 { 10080 {
10085 Efl_Text_Annotate_Annotation *an = fmt->annotation; 10081 Efl_Text_Attribute_Handle *an = fmt->annotation;
10086 10082
10087 fnode = eina_list_data_get(i); 10083 fnode = eina_list_data_get(i);
10088 formats = eina_list_remove_list(formats, i); 10084 formats = eina_list_remove_list(formats, i);
@@ -10092,7 +10088,7 @@ _evas_textblock_node_format_remove_matching(Efl_Canvas_Text_Data *o,
10092 if (an) 10088 if (an)
10093 { 10089 {
10094 _evas_textblock_annotation_remove( 10090 _evas_textblock_annotation_remove(
10095 o, an, EINA_FALSE); 10091 NULL, o, an, EINA_FALSE, EINA_FALSE);
10096 } 10092 }
10097 break; 10093 break;
10098 } 10094 }
@@ -10190,6 +10186,13 @@ _evas_textblock_node_format_remove(Efl_Canvas_Text_Data *o, Evas_Object_Textbloc
10190 _evas_textblock_node_format_free(o, n); 10186 _evas_textblock_node_format_free(o, n);
10191} 10187}
10192 10188
10189void
10190_evas_textblock_annotations_node_format_remove(Evas_Object *eo_obj, Evas_Object_Textblock_Node_Format *n, int visual_adjustment)
10191{
10192 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
10193 _evas_textblock_node_format_remove(o, n, visual_adjustment);
10194}
10195
10193/** 10196/**
10194 * @internal 10197 * @internal
10195 * Sets all the offsets of the format nodes between start and end in the text 10198 * Sets all the offsets of the format nodes between start and end in the text
@@ -15219,6 +15222,12 @@ _efl_canvas_text_efl_text_text_get(const Eo *eo_obj, Efl_Canvas_Text_Data *o)
15219 return o->utf8; 15222 return o->utf8;
15220} 15223}
15221 15224
15225void evas_textblock_async_block(Evas_Object *eo_obj)
15226{
15227 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
15228 ASYNC_BLOCK;
15229}
15230
15222/** 15231/**
15223 * @internal 15232 * @internal
15224 * Returns the value of the current data of list node, 15233 * Returns the value of the current data of list node,
@@ -15228,8 +15237,8 @@ _efl_canvas_text_efl_text_text_get(const Eo *eo_obj, Efl_Canvas_Text_Data *o)
15228 * @param data the data of the current list node. 15237 * @param data the data of the current list node.
15229 * @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE. 15238 * @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
15230 */ 15239 */
15231static Eina_Bool 15240Eina_Bool
15232_evas_textblock_annotation_iterator_next(Efl_Text_Annotate_Annotation_Iterator *it, void **data) 15241_evas_textblock_annotation_iterator_next(Efl_Text_Attribute_Handle_Iterator *it, void **data)
15233{ 15242{
15234 if (!it->current) 15243 if (!it->current)
15235 return EINA_FALSE; 15244 return EINA_FALSE;
@@ -15246,8 +15255,8 @@ _evas_textblock_annotation_iterator_next(Efl_Text_Annotate_Annotation_Iterator *
15246 * @param it the iterator to free 15255 * @param it the iterator to free
15247 * @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE. 15256 * @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
15248 */ 15257 */
15249static void 15258void
15250_evas_textblock_annotation_iterator_free(Efl_Text_Annotate_Annotation_Iterator *it) 15259_evas_textblock_annotation_iterator_free(Efl_Text_Attribute_Handle_Iterator *it)
15251{ 15260{
15252 EINA_MAGIC_SET(&it->iterator, 0); 15261 EINA_MAGIC_SET(&it->iterator, 0);
15253 it->current = NULL; 15262 it->current = NULL;
@@ -15267,7 +15276,7 @@ _evas_textblock_annotation_iterator_new(Eina_List *list)
15267{ 15276{
15268 Evas_Textblock_Selection_Iterator *it; 15277 Evas_Textblock_Selection_Iterator *it;
15269 15278
15270 it = calloc(1, sizeof(Efl_Text_Annotate_Annotation_Iterator)); 15279 it = calloc(1, sizeof(Efl_Text_Attribute_Handle_Iterator));
15271 if (!it) return NULL; 15280 if (!it) return NULL;
15272 15281
15273 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); 15282 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
@@ -15283,24 +15292,24 @@ _evas_textblock_annotation_iterator_new(Eina_List *list)
15283 return &it->iterator; 15292 return &it->iterator;
15284} 15293}
15285 15294
15286static void 15295void
15287_textblock_cursor_pos_at_fnode_set(const Eo *eo_obj EINA_UNUSED, 15296_textblock_cursor_pos_at_fnode_set(Efl_Text_Cursor_Handle *cur,
15288 Efl_Text_Cursor_Handle *cur,
15289 Evas_Object_Textblock_Node_Format *fnode) 15297 Evas_Object_Textblock_Node_Format *fnode)
15290{ 15298{
15291 cur->node = fnode->text_node; 15299 cur->node = fnode->text_node;
15292 cur->pos = _evas_textblock_node_format_pos_get(fnode); 15300 cur->pos = _evas_textblock_node_format_pos_get(fnode);
15293} 15301}
15294 15302
15295static Eina_Bool 15303Eina_Bool
15296_textblock_annotation_set(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o, 15304_evas_textblock_annotations_set(Eo *eo_obj,
15297 Efl_Text_Annotate_Annotation *an, 15305 Efl_Text_Attribute_Handle *an,
15298 Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end, 15306 Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
15299 const char *format, Eina_Bool is_item) 15307 const char *format, Eina_Bool is_item)
15300{ 15308{
15301 int len; 15309 int len;
15302 char *buf; 15310 char *buf;
15303 Evas_Textblock_Node_Format *fnode; 15311 Evas_Textblock_Node_Format *fnode;
15312 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
15304 15313
15305 if (an->is_item) 15314 if (an->is_item)
15306 { 15315 {
@@ -15332,60 +15341,20 @@ _textblock_annotation_set(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o,
15332 return EINA_TRUE; 15341 return EINA_TRUE;
15333} 15342}
15334 15343
15335EOLIAN static const char * 15344Eina_Inlist *
15336_efl_canvas_text_efl_text_annotate_annotation_get(const Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o EINA_UNUSED, 15345_evas_textblock_annotations_get(Eo *eo_obj)
15337 Efl_Text_Annotate_Annotation *annotation)
15338{ 15346{
15339 if (!annotation || (annotation->obj != eo_obj)) 15347 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
15340 { 15348 return (Eina_Inlist*)o->annotations;
15341 ERR("Used invalid handle or of a different object");
15342 return NULL;
15343 }
15344
15345 return (annotation->start_node ? annotation->start_node->format : NULL);
15346} 15349}
15347 15350
15348EOLIAN static Eina_Bool 15351void
15349_efl_canvas_text_efl_text_annotate_annotation_set(Eo *eo_obj, 15352_evas_textblock_annotation_remove(Eo *eo_obj, Efl_Canvas_Text_Data *o,
15350 Efl_Canvas_Text_Data *o, Efl_Text_Annotate_Annotation *annotation, 15353 Efl_Text_Attribute_Handle *an, Eina_Bool remove_nodes, Eina_Bool invalidate)
15351 const char *format)
15352{ 15354{
15353 ASYNC_BLOCK; 15355 if (!o)
15354 Efl_Text_Cursor_Handle start, end; 15356 o = efl_data_scope_get(eo_obj, MY_CLASS);
15355 Eina_Bool ret = EINA_TRUE;
15356
15357 if (!annotation || (annotation->obj != eo_obj))
15358 {
15359 ERR("Used invalid handle or of a different object");
15360 return EINA_FALSE;
15361 }
15362
15363 if (!annotation->start_node || !annotation->end_node) return EINA_FALSE;
15364 if (!format || (format[0] == '\0')) return EINA_FALSE;
15365
15366 _evas_textblock_cursor_init(&start, eo_obj);
15367 _evas_textblock_cursor_init(&end, eo_obj);
15368
15369 /* XXX: Not efficient but works and saves code */
15370 _textblock_cursor_pos_at_fnode_set(eo_obj, &start, annotation->start_node);
15371 _textblock_cursor_pos_at_fnode_set(eo_obj, &end, annotation->end_node);
15372
15373 _evas_textblock_node_format_remove(o, annotation->start_node, 0);
15374 _evas_textblock_node_format_remove(o, annotation->end_node, 0);
15375
15376 if (!_textblock_annotation_set(eo_obj, o, annotation, &start, &end, format,
15377 EINA_FALSE))
15378 {
15379 ret = EINA_FALSE;
15380 }
15381
15382 return ret;
15383}
15384 15357
15385static void
15386_evas_textblock_annotation_remove(Efl_Canvas_Text_Data *o,
15387 Efl_Text_Annotate_Annotation *an, Eina_Bool remove_nodes)
15388{
15389 if (remove_nodes) 15358 if (remove_nodes)
15390 { 15359 {
15391 if (an->is_item) 15360 if (an->is_item)
@@ -15393,64 +15362,53 @@ _evas_textblock_annotation_remove(Efl_Canvas_Text_Data *o,
15393 /* Remove the OBJ character along with the cursor. */ 15362 /* Remove the OBJ character along with the cursor. */
15394 Efl_Text_Cursor_Handle cur; 15363 Efl_Text_Cursor_Handle cur;
15395 _evas_textblock_cursor_init(&cur, an->obj); 15364 _evas_textblock_cursor_init(&cur, an->obj);
15396 _textblock_cursor_pos_at_fnode_set(an->obj, &cur, an->start_node); 15365 _textblock_cursor_pos_at_fnode_set(&cur, an->start_node);
15397 evas_textblock_cursor_char_delete(&cur); 15366 evas_textblock_cursor_char_delete(&cur);
15398 return; // 'an' should be deleted after char deletion. 15367 return; // 'an' should be deleted after char deletion.
15399 } 15368 }
15400 _evas_textblock_node_format_remove(o, an->start_node, 0); 15369 _evas_textblock_node_format_remove(o, an->start_node, 0);
15401 _evas_textblock_node_format_remove(o, an->end_node, 0); 15370 _evas_textblock_node_format_remove(o, an->end_node, 0);
15402 } 15371 }
15403 o->annotations = (Efl_Text_Annotate_Annotation *) 15372 o->annotations = (Efl_Text_Attribute_Handle *)
15404 eina_inlist_remove(EINA_INLIST_GET(o->annotations), 15373 eina_inlist_remove(EINA_INLIST_GET(o->annotations),
15405 EINA_INLIST_GET(an)); 15374 EINA_INLIST_GET(an));
15406 free(an); 15375 free(an);
15407} 15376 if (invalidate)
15377 {
15378 o->format_changed = EINA_TRUE;
15408 15379
15409static void 15380 //XXX: It's a workaround. The underlying problem is that only new format
15410_evas_textblock_annotations_clear(Efl_Canvas_Text_Data *o) 15381 // nodes are checks when their respective text nodes are invalidated (see
15411{ 15382 // _format_changes_invalidate_text_nodes). Complete removal of the format
15412 Efl_Text_Annotate_Annotation *an; 15383 // nodes was not handled properly (as formats could only be removed via
15384 // text changes e.g. deleting characters).
15385 _evas_textblock_invalidate_all(o);
15413 15386
15414 EINA_INLIST_FREE(o->annotations, an) 15387 _evas_textblock_changed(o, eo_obj);
15415 {
15416 _evas_textblock_annotation_remove(o, an, EINA_TRUE);
15417 } 15388 }
15418} 15389}
15419 15390
15420EOLIAN static Eina_Bool 15391void
15421_efl_canvas_text_efl_text_annotate_annotation_del(Eo *eo_obj EINA_UNUSED, 15392_evas_textblock_annotations_clear(const Eo *eo_obj)
15422 Efl_Canvas_Text_Data *o, Efl_Text_Annotate_Annotation *annotation)
15423{ 15393{
15424 ASYNC_BLOCK; 15394 Efl_Text_Attribute_Handle *an;
15425 if (!annotation || (annotation->obj != eo_obj)) 15395 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
15396
15397 EINA_INLIST_FREE(o->annotations, an)
15426 { 15398 {
15427 ERR("Used invalid handle or of a different object"); 15399 _evas_textblock_annotation_remove(NULL, o, an, EINA_TRUE, EINA_FALSE);
15428 return EINA_FALSE;
15429 } 15400 }
15430
15431 _evas_textblock_annotation_remove(o, annotation, EINA_TRUE);
15432 o->format_changed = EINA_TRUE;
15433
15434 //XXX: It's a workaround. The underlying problem is that only new format
15435 // nodes are checks when their respective text nodes are invalidated (see
15436 // _format_changes_invalidate_text_nodes). Complete removal of the format
15437 // nodes was not handled properly (as formats could only be removed via
15438 // text changes e.g. deleting characters).
15439 _evas_textblock_invalidate_all(o);
15440
15441 _evas_textblock_changed(o, eo_obj);
15442 return EINA_TRUE;
15443} 15401}
15444 15402
15445static Efl_Text_Annotate_Annotation * 15403Efl_Text_Attribute_Handle *
15446_textblock_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o, 15404_evas_textblock_annotations_insert(Eo *eo_obj, Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
15447 Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
15448 const char *format, Eina_Bool is_item) 15405 const char *format, Eina_Bool is_item)
15449{ 15406{
15450 Efl_Text_Annotate_Annotation *ret = NULL; 15407 Efl_Text_Attribute_Handle *ret = NULL;
15451 Eina_Strbuf *buf; 15408 Eina_Strbuf *buf;
15452 Eina_Bool first = EINA_TRUE; 15409 Eina_Bool first = EINA_TRUE;
15453 const char *item; 15410 const char *item;
15411 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
15454 15412
15455 if (!format || (format[0] == '\0') || 15413 if (!format || (format[0] == '\0') ||
15456 evas_textblock_cursor_compare(start, end) > 0) 15414 evas_textblock_cursor_compare(start, end) > 0)
@@ -15489,15 +15447,15 @@ _textblock_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o,
15489 format = eina_strbuf_string_get(buf); 15447 format = eina_strbuf_string_get(buf);
15490 if (format && (format[0] != '\0')) 15448 if (format && (format[0] != '\0'))
15491 { 15449 {
15492 ret = calloc(1, sizeof(Efl_Text_Annotate_Annotation)); 15450 ret = calloc(1, sizeof(Efl_Text_Attribute_Handle));
15493 ret->obj = eo_obj; 15451 ret->obj = eo_obj;
15494 15452
15495 o->annotations = (Efl_Text_Annotate_Annotation *) 15453 o->annotations = (Efl_Text_Attribute_Handle *)
15496 eina_inlist_append(EINA_INLIST_GET(o->annotations), 15454 eina_inlist_append(EINA_INLIST_GET(o->annotations),
15497 EINA_INLIST_GET(ret)); 15455 EINA_INLIST_GET(ret));
15498 15456
15499 15457
15500 _textblock_annotation_set(eo_obj, o, ret, start, end, format, is_item); 15458 _evas_textblock_annotations_set(eo_obj, ret, start, end, format, is_item);
15501 ret->is_item = is_item; 15459 ret->is_item = is_item;
15502 _evas_textblock_changed(o, eo_obj); 15460 _evas_textblock_changed(o, eo_obj);
15503 } 15461 }
@@ -15507,123 +15465,6 @@ _textblock_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o,
15507 return ret; 15465 return ret;
15508} 15466}
15509 15467
15510EOLIAN static Efl_Text_Annotate_Annotation *
15511_efl_canvas_text_efl_text_annotate_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o,
15512 Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
15513 const char *format)
15514{
15515 ASYNC_BLOCK;
15516 Efl_Text_Annotate_Annotation *ret;
15517
15518 ret = _textblock_annotation_insert(eo_obj, o, start, end, format,
15519 EINA_FALSE);
15520 efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
15521 return ret;
15522}
15523
15524EOLIAN static Eina_Iterator *
15525_efl_canvas_text_efl_text_annotate_range_annotations_get(const Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED,
15526 const Evas_Textblock_Cursor *start, const Evas_Textblock_Cursor *end)
15527{
15528 Eina_List *lst = NULL;
15529 Efl_Text_Annotate_Annotation *it;
15530
15531 EINA_INLIST_FOREACH(o->annotations, it)
15532 {
15533 Efl_Text_Cursor_Handle start2, end2;
15534 _evas_textblock_cursor_init(&start2, eo_obj);
15535 _evas_textblock_cursor_init(&end2, eo_obj);
15536
15537 if (!it->start_node || !it->end_node) continue;
15538 _textblock_cursor_pos_at_fnode_set(eo_obj, &start2, it->start_node);
15539 _textblock_cursor_pos_at_fnode_set(eo_obj, &end2, it->end_node);
15540 evas_textblock_cursor_char_prev(&end2);
15541 if (!((evas_textblock_cursor_compare(&start2, end) > 0) ||
15542 (evas_textblock_cursor_compare(&end2, start) < 0)))
15543 {
15544 lst = eina_list_append(lst, it);
15545 }
15546 }
15547 return _evas_textblock_annotation_iterator_new(lst);
15548}
15549
15550EOLIAN static Efl_Text_Annotate_Annotation *
15551_efl_canvas_text_efl_text_annotate_cursor_item_insert(Eo *eo_obj,
15552 Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Handle *cur,
15553 const char *item, const char *format)
15554{
15555 Eina_Strbuf *buf = eina_strbuf_new();
15556
15557 eina_strbuf_append_printf(buf, "%s href=%s", format, item);
15558
15559 Efl_Text_Annotate_Annotation *ret =
15560 _textblock_annotation_insert(cur->obj, o, cur, cur,
15561 eina_strbuf_string_get(buf), EINA_TRUE);
15562 eina_strbuf_free(buf);
15563 efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
15564 return ret;
15565}
15566
15567EOLIAN static Efl_Text_Annotate_Annotation *
15568_efl_canvas_text_efl_text_annotate_cursor_item_annotation_get(const Eo *eo_obj EINA_UNUSED,
15569 Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Handle *cur)
15570{
15571 Eina_Iterator *it;
15572 Efl_Text_Annotate_Annotation *data, *ret = NULL;
15573
15574 it = efl_text_range_annotations_get(cur->obj,
15575 cur, cur);
15576 EINA_ITERATOR_FOREACH(it, data)
15577 {
15578 if (data->is_item)
15579 {
15580 ret = data;
15581 break;
15582 }
15583 }
15584 eina_iterator_free(it);
15585 return ret;
15586}
15587
15588EOLIAN static Eina_Bool
15589_efl_canvas_text_efl_text_annotate_annotation_is_item(Eo *eo_obj EINA_UNUSED,
15590 Efl_Canvas_Text_Data *o EINA_UNUSED,
15591 Efl_Text_Annotate_Annotation *annotation)
15592{
15593 if (!annotation || (annotation->obj != eo_obj))
15594 {
15595 ERR("Used invalid handle or of a different object");
15596 return EINA_FALSE;
15597 }
15598
15599 return annotation->is_item;
15600}
15601
15602EOLIAN static Eina_Bool
15603_efl_canvas_text_efl_text_annotate_item_geometry_get(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED,
15604 const Efl_Text_Annotate_Annotation *an, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
15605{
15606 Efl_Text_Cursor_Handle cur;
15607
15608 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
15609 evas_object_async_block(obj);
15610 _relayout_if_needed(eo_obj, o);
15611
15612 _evas_textblock_cursor_init(&cur, eo_obj);
15613 _textblock_cursor_pos_at_fnode_set(eo_obj, &cur, an->start_node);
15614 return _evas_textblock_cursor_format_item_geometry_get(&cur, cx, cy, cw, ch);
15615}
15616
15617EOLIAN static void
15618_efl_canvas_text_efl_text_annotate_annotation_positions_get(Eo *eo_obj,
15619 Efl_Canvas_Text_Data *o EINA_UNUSED,
15620 const Efl_Text_Annotate_Annotation *annotation,
15621 Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end)
15622{
15623 _textblock_cursor_pos_at_fnode_set(eo_obj, start, annotation->start_node);
15624 _textblock_cursor_pos_at_fnode_set(eo_obj, end, annotation->end_node);
15625}
15626
15627static void 15468static void
15628_canvas_text_format_changed(Eo *eo_obj, Efl_Canvas_Text_Data *o) 15469_canvas_text_format_changed(Eo *eo_obj, Efl_Canvas_Text_Data *o)
15629{ 15470{
diff --git a/src/lib/evas/canvas/meson.build b/src/lib/evas/canvas/meson.build
index d9e6798..07dd725 100644
--- a/src/lib/evas/canvas/meson.build
+++ b/src/lib/evas/canvas/meson.build
@@ -56,6 +56,7 @@ pub_eo_files = [
56 'efl_canvas_event_grabber.eo', 56 'efl_canvas_event_grabber.eo',
57 'efl_text_cursor.eo', 57 'efl_text_cursor.eo',
58 'efl_canvas_text.eo', 58 'efl_canvas_text.eo',
59 'efl_text_attribute_factory.eo',
59 'efl_canvas_object_animation.eo', 60 'efl_canvas_object_animation.eo',
60] 61]
61 62
@@ -208,7 +209,8 @@ evas_src += files([
208 'evas_canvas3d_node_callback.h', 209 'evas_canvas3d_node_callback.h',
209 'evas_canvas3d_eet.c', 210 'evas_canvas3d_eet.c',
210 'efl_canvas_object_animation.c', 211 'efl_canvas_object_animation.c',
211 'efl_text_cursor.c' 212 'efl_text_cursor.c',
213 'efl_text_attribute_factory.c'
212 ]) 214 ])
213 215
214evas_include_directories += include_directories('.') 216evas_include_directories += include_directories('.')
diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c
index 860c674..163d403 100644
--- a/src/tests/evas/evas_test_textblock.c
+++ b/src/tests/evas/evas_test_textblock.c
@@ -37,6 +37,7 @@ static const char *style_buf =
37 Evas_Object *tb; \ 37 Evas_Object *tb; \
38 Evas_Textblock_Style *st; \ 38 Evas_Textblock_Style *st; \
39 Evas_Textblock_Cursor *cur; \ 39 Evas_Textblock_Cursor *cur; \
40 Efl_Text_Cursor *cur_obj; \
40 evas = EVAS_TEST_INIT_EVAS(); \ 41 evas = EVAS_TEST_INIT_EVAS(); \
41 evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \ 42 evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \
42 tb = evas_object_textblock_add(evas); \ 43 tb = evas_object_textblock_add(evas); \
@@ -48,6 +49,9 @@ static const char *style_buf =
48 fail_if(strcmp(style_buf, evas_textblock_style_get(st))); \ 49 fail_if(strcmp(style_buf, evas_textblock_style_get(st))); \
49 evas_object_textblock_style_set(tb, st); \ 50 evas_object_textblock_style_set(tb, st); \
50 cur = evas_object_textblock_cursor_new(tb); \ 51 cur = evas_object_textblock_cursor_new(tb); \
52 cur_obj =efl_canvas_text_cursor_create(tb);\
53 (void) cur_obj;\
54 (void) cur;\
51do \ 55do \
52{ \ 56{ \
53} \ 57} \
@@ -58,6 +62,7 @@ do \
58{ \ 62{ \
59 evas_textblock_cursor_free(cur); \ 63 evas_textblock_cursor_free(cur); \
60 evas_object_del(tb); \ 64 evas_object_del(tb); \
65 efl_del(cur_obj); \
61 evas_textblock_style_free(st); \ 66 evas_textblock_style_free(st); \
62 evas_free(evas); \ 67 evas_free(evas); \
63} \ 68} \
@@ -4304,43 +4309,6 @@ EFL_START_TEST(evas_textblock_text_iface)
4304} 4309}
4305EFL_END_TEST; 4310EFL_END_TEST;
4306 4311
4307static void
4308_test_check_annotation(Evas_Object *tb,
4309 size_t start_pos, size_t end_pos,
4310 size_t len, const char **formats)
4311{
4312 Efl_Text_Annotate_Annotation *an;
4313 Efl_Text_Cursor_Handle *start, *end;
4314
4315 start = evas_object_textblock_cursor_new(tb);
4316 end = evas_object_textblock_cursor_new(tb);
4317
4318 evas_textblock_cursor_pos_set(start, start_pos);
4319 evas_textblock_cursor_pos_set(end, end_pos);
4320
4321 Eina_Iterator *it =
4322 efl_text_range_annotations_get(tb, start, end);
4323
4324 evas_textblock_cursor_free(start);
4325 evas_textblock_cursor_free(end);
4326
4327 size_t i = 0;
4328 EINA_ITERATOR_FOREACH(it, an)
4329 {
4330 const char *fmt = efl_text_annotation_get(tb,
4331 an);
4332 ck_assert_msg((i < len),
4333 "No formats to check but current annotation is: %s\n", fmt);
4334 ck_assert_str_eq(fmt, *formats);
4335 formats++;
4336 i++;
4337 }
4338 ck_assert_msg((i == len),
4339 "Expected next format (index %lu): %s, but reached end of annotations\n",
4340 i, *formats);
4341
4342 eina_iterator_free(it);
4343}
4344 4312
4345#define _COMP_STR(...) ((const char *[]) { __VA_ARGS__ }) 4313#define _COMP_STR(...) ((const char *[]) { __VA_ARGS__ })
4346#define _CREATE_PARAMS(X) (sizeof(X) / sizeof(X[0])), (X) 4314#define _CREATE_PARAMS(X) (sizeof(X) / sizeof(X[0])), (X)
@@ -4349,11 +4317,10 @@ _test_check_annotation(Evas_Object *tb,
4349EFL_START_TEST(evas_textblock_annotation) 4317EFL_START_TEST(evas_textblock_annotation)
4350{ 4318{
4351 START_TB_TEST(); 4319 START_TB_TEST();
4352 Efl_Text_Annotate_Annotation *an, *an2; 4320 Efl_Text_Cursor *start, *end;
4353 Efl_Text_Cursor_Handle *start, *end;
4354 4321
4355 start = evas_object_textblock_cursor_new(tb); 4322 start = efl_canvas_text_cursor_create(tb);
4356 end = evas_object_textblock_cursor_new(tb); 4323 end = efl_canvas_text_cursor_create(tb);
4357 4324
4358 const char *buf = 4325 const char *buf =
4359 "This text will check annotation." 4326 "This text will check annotation."
@@ -4365,167 +4332,21 @@ EFL_START_TEST(evas_textblock_annotation)
4365 efl_text_set(tb, buf); 4332 efl_text_set(tb, buf);
4366 4333
4367 /* Check some trivial cases */ 4334 /* Check some trivial cases */
4368 evas_textblock_cursor_pos_set(start, 0);
4369 evas_textblock_cursor_pos_set(end, 3);
4370 ck_assert(!efl_text_annotation_insert(tb, start, end, NULL));
4371 evas_textblock_cursor_pos_set(start, 0);
4372 evas_textblock_cursor_pos_set(end, 3);
4373 ck_assert(!efl_text_annotation_insert(tb, start, end, ""));
4374 evas_textblock_cursor_pos_set(start, 1);
4375 evas_textblock_cursor_pos_set(end, 0);
4376 ck_assert(!efl_text_annotation_insert(tb, start, end, "color=#fff"));
4377
4378 /* Insert and check correct positions */
4379 _test_check_annotation(tb, 0, 10, _COMP_PARAMS());
4380
4381 evas_textblock_cursor_pos_set(start, 0);
4382 evas_textblock_cursor_pos_set(end, 3);
4383 efl_text_annotation_insert(tb, start, end, "font_weight=bold");
4384 _test_check_annotation(tb, 0, 2, _COMP_PARAMS("font_weight=bold"));
4385 _test_check_annotation(tb, 0, 2, _COMP_PARAMS("font_weight=bold"));
4386 _test_check_annotation(tb, 4, 10, _COMP_PARAMS());
4387
4388 evas_textblock_cursor_pos_set(start, 50);
4389 evas_textblock_cursor_pos_set(end, 60);
4390 efl_text_annotation_insert(tb, start, end, "color=#0ff");
4391 _test_check_annotation(tb, 0, 49, _COMP_PARAMS("font_weight=bold"));
4392 _test_check_annotation(tb, 0, 50, _COMP_PARAMS("font_weight=bold", "color=#0ff"));
4393 _test_check_annotation(tb, 0, 55, _COMP_PARAMS("font_weight=bold", "color=#0ff"));
4394 _test_check_annotation(tb, 0, 59, _COMP_PARAMS("font_weight=bold", "color=#0ff"));
4395 _test_check_annotation(tb, 40, 50, _COMP_PARAMS("color=#0ff"));
4396 _test_check_annotation(tb, 40, 51, _COMP_PARAMS("color=#0ff"));
4397 _test_check_annotation(tb, 40, 61, _COMP_PARAMS("color=#0ff"));
4398 _test_check_annotation(tb, 59, 60, _COMP_PARAMS("color=#0ff"));
4399 _test_check_annotation(tb, 60, 61, _COMP_PARAMS());
4400
4401 /* See that annotation's positions are updated as text is inserted */
4402 efl_text_set(tb, "hello");
4403 evas_textblock_cursor_pos_set(start, 0);
4404 evas_textblock_cursor_pos_set(end, 2);
4405 an = efl_text_annotation_insert(tb, start, end, "color=#fff");
4406 _test_check_annotation(tb, 2, 3, _COMP_PARAMS());
4407 evas_textblock_cursor_pos_set(cur, 0);
4408 evas_textblock_cursor_text_append(cur, "a");
4409 _test_check_annotation(tb, 2, 3, _COMP_PARAMS("color=#fff"));
4410 _test_check_annotation(tb, 3, 4, _COMP_PARAMS());
4411
4412 /* Replace annotations's format */
4413 efl_text_annotation_set(tb, an, "font_size=14");
4414 _test_check_annotation(tb, 2, 3, _COMP_PARAMS("font_size=14"));
4415 _test_check_annotation(tb, 3, 4, _COMP_PARAMS());
4416 4335
4417 efl_text_set(tb, "hello world"); 4336 efl_text_cursor_position_set(start, 0);
4418 evas_textblock_cursor_pos_set(start, 0); 4337 efl_text_cursor_position_set(end, 3);
4419 evas_textblock_cursor_pos_set(end, 2); 4338 efl_text_attribute_factory_attribute_insert(start, end, "font_size=80");
4420 an = efl_text_annotation_insert(tb, start, end, "color=#fff"); 4339 efl_text_cursor_position_set(start, 1);
4421 evas_textblock_cursor_pos_set(start, 2); 4340 efl_text_cursor_position_set(end, 2);
4422 evas_textblock_cursor_pos_set(end, 3); 4341 efl_text_attribute_factory_attribute_insert(start, end, "font=arial");
4423 an2 = efl_text_annotation_insert(tb, start, end, "font_size=14"); 4342 efl_text_cursor_position_set(start, 2);
4424 _test_check_annotation(tb, 0, 1, _COMP_PARAMS("color=#fff")); 4343 efl_text_cursor_position_set(end, 3);
4425 _test_check_annotation(tb, 2, 3, _COMP_PARAMS("font_size=14")); 4344 efl_text_attribute_factory_attribute_insert(start, end, "color=#fff");
4426 _test_check_annotation(tb, 0, 3, _COMP_PARAMS("color=#fff", "font_size=14"));
4427 efl_text_annotation_set(tb, an, "font_size=10");
4428 efl_text_annotation_set(tb, an2, "color=#000");
4429 _test_check_annotation(tb, 2, 3, _COMP_PARAMS("color=#000"));
4430 _test_check_annotation(tb, 0, 1, _COMP_PARAMS("font_size=10"));
4431 _test_check_annotation(tb, 0, 3, _COMP_PARAMS("font_size=10", "color=#000"));
4432
4433 /* Delete annotations directly */
4434 efl_text_set(tb, "hello world");
4435 evas_textblock_cursor_pos_set(start, 0);
4436 evas_textblock_cursor_pos_set(end, 2);
4437 an = efl_text_annotation_insert(tb, start, end, "color=#fff");
4438 evas_textblock_cursor_pos_set(start, 3);
4439 evas_textblock_cursor_pos_set(end, 4);
4440 an2 = efl_text_annotation_insert(tb, start, end, "font_size=14");
4441 efl_text_annotation_del(tb, an);
4442 _test_check_annotation(tb, 0, 3, _COMP_PARAMS("font_size=14"));
4443 efl_text_annotation_del(tb, an2);
4444 _test_check_annotation(tb, 0, 3, _COMP_PARAMS());
4445 evas_textblock_cursor_pos_set(start, 0);
4446 evas_textblock_cursor_pos_set(end, 1);
4447 an = efl_text_annotation_insert(tb, start, end, "color=#fff");
4448 _test_check_annotation(tb, 1, 3, _COMP_PARAMS());
4449 _test_check_annotation(tb, 0, 0, _COMP_PARAMS("color=#fff"));
4450 efl_text_annotation_del(tb, an);
4451 _test_check_annotation(tb, 0, 0, _COMP_PARAMS());
4452
4453 /* Check blocking of "item formats" */
4454 efl_text_set(tb, "hello world");
4455 evas_textblock_cursor_pos_set(start, 0);
4456 evas_textblock_cursor_pos_set(end, 1);
4457 efl_text_annotation_insert(tb, start, end, "ps");
4458 _test_check_annotation(tb, 0, 1, _COMP_PARAMS());
4459 evas_textblock_cursor_pos_set(start, 0);
4460 evas_textblock_cursor_pos_set(end, 1);
4461 efl_text_annotation_insert(tb, start, end, "color=#fff");
4462 _test_check_annotation(tb, 0, 1, _COMP_PARAMS("color=#fff"));
4463 evas_textblock_cursor_pos_set(start, 2);
4464 evas_textblock_cursor_pos_set(end, 3);
4465 efl_text_annotation_insert(tb, start, end, "br");
4466 evas_textblock_cursor_pos_set(start, 6);
4467 evas_textblock_cursor_pos_set(end, 7);
4468 efl_text_annotation_insert(tb, start, end, "item");
4469 _test_check_annotation(tb, 0, 8, _COMP_PARAMS("color=#fff"));
4470
4471 /* Check "item" annotations */
4472 efl_text_set(tb, "abcd");
4473 evas_textblock_cursor_pos_set(cur, 4);
4474 an = efl_text_cursor_item_insert(tb, cur, "", "size=16x16");
4475 _test_check_annotation(tb, 4, 4, _COMP_PARAMS("size=16x16 href="));
4476
4477 /* Check that format is not extended if it's an "object item" */
4478 evas_textblock_cursor_pos_set(cur, 5);
4479 evas_textblock_cursor_text_prepend(cur, "a");
4480 _test_check_annotation(tb, 5, 7, _COMP_PARAMS());
4481 _test_check_annotation(tb, 0, 3, _COMP_PARAMS());
4482
4483 /* Remove annotation of "item" also removes the OBJ character */
4484 {
4485 int blen, len;
4486 evas_textblock_cursor_pos_set(cur, 5);
4487 blen = evas_textblock_cursor_paragraph_text_length_get(cur);
4488 efl_text_annotation_del(tb, an);
4489 len = evas_textblock_cursor_paragraph_text_length_get(cur);
4490 ck_assert_int_eq(len, blen - 1);
4491 _test_check_annotation(tb, 0, 5, _COMP_PARAMS());
4492 }
4493
4494 /* Using annotations with new text API */
4495 efl_text_set(tb, "hello");
4496 evas_textblock_cursor_pos_set(start, 0);
4497 evas_textblock_cursor_pos_set(end, 5);
4498 efl_text_annotation_insert(tb, start, end, "color=#fff");
4499 _test_check_annotation(tb, 3, 3, _COMP_PARAMS("color=#fff"));
4500 /* Old API */
4501 evas_textblock_cursor_pos_set(cur, 5);
4502 evas_textblock_cursor_text_prepend(cur, "a");
4503 _test_check_annotation(tb, 0, 0, _COMP_PARAMS("color=#fff"));
4504 _test_check_annotation(tb, 5, 5, _COMP_PARAMS());
4505
4506 /* Specific case with PS */
4507 efl_text_set(tb, "hello\nworld");
4508 evas_textblock_cursor_pos_set(start, 0);
4509 evas_textblock_cursor_pos_set(end, 5);
4510 efl_text_annotation_insert(tb, start, end, "color=#fff");
4511 _test_check_annotation(tb, 4, 4, _COMP_PARAMS("color=#fff"));
4512 evas_textblock_cursor_pos_set(cur, 4);
4513 /* Cursor position is now: hello|\nworld */
4514 evas_textblock_cursor_text_prepend(cur, "a");
4515 _test_check_annotation(tb, 0, 0, _COMP_PARAMS("color=#fff"));
4516 _test_check_annotation(tb, 5, 5, _COMP_PARAMS("color=#fff"));
4517
4518 /* Test getting of object item */
4519 evas_textblock_cursor_pos_set(cur, 4);
4520 an = efl_text_cursor_item_annotation_get(tb, cur);
4521 ck_assert(!an);
4522 an = efl_text_cursor_item_insert(tb, cur, "", "size=16x16");
4523 evas_textblock_cursor_pos_set(cur, 4);
4524 an = efl_text_cursor_item_annotation_get(tb, cur);
4525 ck_assert(an);
4526 ck_assert_str_eq("size=16x16 href=", efl_text_annotation_get(tb, an));
4527 4345
4528 END_TB_TEST(); 4346 efl_text_cursor_position_set(start, 0);
4347 efl_text_cursor_position_set(end, 3);
4348 unsigned int count = efl_text_attribute_factory_attribute_clear(start, end);
4349 fail_if(count != 3);
4529} 4350}
4530EFL_END_TEST; 4351EFL_END_TEST;
4531 4352
@@ -4543,7 +4364,7 @@ EFL_END_TEST;
4543 fail_if(!efl_canvas_text_style_get(txt, NULL) || \ 4364 fail_if(!efl_canvas_text_style_get(txt, NULL) || \
4544 strcmp(style_buf, efl_canvas_text_style_get(txt, NULL))); \ 4365 strcmp(style_buf, efl_canvas_text_style_get(txt, NULL))); \
4545 cur_obj = efl_canvas_text_cursor_create(txt);\ 4366 cur_obj = efl_canvas_text_cursor_create(txt);\
4546 cur = efl_text_cursor_handle_get(cur_obj); \ 4367 cur = evas_object_textblock_cursor_new(txt); \
4547 fail_if(!cur); \ 4368 fail_if(!cur); \
4548do \ 4369do \
4549{ \ 4370{ \
@@ -4554,6 +4375,7 @@ while (0)
4554do \ 4375do \
4555{ \ 4376{ \
4556 efl_del(cur_obj); \ 4377 efl_del(cur_obj); \
4378 evas_textblock_cursor_free(cur); \
4557 efl_del(txt); \ 4379 efl_del(txt); \
4558 evas_free(evas); \ 4380 evas_free(evas); \
4559} \ 4381} \