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
This commit is contained in:
Ali Alzyod 2019-11-27 13:04:31 +09:00 committed by WooHyun Jung
parent f10c91cda9
commit c7f37fe618
21 changed files with 432 additions and 811 deletions

View File

@ -366,7 +366,6 @@ void test_code_diff_inline(void *data, Evas_Object *obj, void *event_info);
void test_efl_ui_text(void *data, Evas_Object *obj, void *event_info);
void test_efl_ui_text_inputfield(void *data, Evas_Object *obj, void *event_info);
void test_efl_ui_text_label(void *data, Evas_Object *obj, void *event_info);
void test_ui_text_item_factory(void *data, Evas_Object *obj, void *event_info);
void test_evas_mask(void *data, Edje_Object *obj, void *event_info);
void test_gfx_filters(void *data, Evas_Object *obj, void *event_info);
void test_evas_snapshot(void *data, Evas_Object *obj, void *event_info);
@ -941,7 +940,6 @@ add_tests:
ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text", test_efl_ui_text);
ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text Input Field", test_efl_ui_text_inputfield);
ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Text Label", test_efl_ui_text_label);
ADD_TEST_EO(NULL, "Entries", "Ui.Text Item Factory", test_ui_text_item_factory);
ADD_TEST_EO(NULL, "Entries", "Efl.Ui.Tags", test_ui_tags);
//------------------------------//

View File

@ -5,6 +5,7 @@
#include <Efl_Ui.h>
#include <Elementary.h>
#include "elm_priv.h" //FIXME remove this once efl.ui.text doesn't need elm_general.h
static void
_apply_style(Eo *obj, size_t start_pos, size_t end_pos, const char *style)
{
@ -16,7 +17,7 @@ _apply_style(Eo *obj, size_t start_pos, size_t end_pos, const char *style)
efl_text_cursor_position_set(start, start_pos);
efl_text_cursor_position_set(end, end_pos);
efl_text_annotation_insert(obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end), style);
efl_text_attribute_factory_attribute_insert(start, end, style);
efl_del(start);
efl_del(end);
@ -235,162 +236,3 @@ test_efl_ui_text_inputfield(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED
efl_gfx_entity_size_set(win, EINA_SIZE2D(300, 200));
}
#define IMAGES_SZ 5
static const char *images[IMAGES_SZ] = {
"sky", "logo", "dog", "eet_rock", "eet_plant" };
static void
_on_factory_bt_image_clicked(void *data, const Efl_Event *event EINA_UNUSED)
{
Evas_Object *en = data;
static int image_idx = 0;
image_idx = (image_idx + 1) % IMAGES_SZ;
efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(efl_text_interactive_main_cursor_get(en)),
images[image_idx], "size=32x32");
printf("Inserted image: key = %s\n", images[image_idx]);
}
static void
_on_factory_bt_emoticon_clicked(void *data, const Efl_Event *event EINA_UNUSED)
{
Evas_Object *en = data;
efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(efl_text_interactive_main_cursor_get(en)),
"emoticon/evil-laugh", "size=32x32");
}
static struct
{
const char *name;
Eo *item_factory;
} factories[3];
static void
_on_factory_bt_factory_clicked(void *data, const Efl_Event *event EINA_UNUSED)
{
Evas_Object *en = data;
static int item_factory_idx = 0;
item_factory_idx = (item_factory_idx + 1) % 3;
efl_ui_text_item_factory_set(en, factories[item_factory_idx].item_factory);
printf("Factory set to: %s\n", factories[item_factory_idx].name);
}
#define FACTORY_NONE 0
#define FACTORY_IMAGE 1
#define FACTORY_EMOTICON 2
void
test_ui_text_item_factory(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Evas_Object *win, *bx, *bx2, *bt, *en;
Efl_Text_Cursor *main_cur, *cur;
char buf[128];
Eina_File *f;
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
efl_text_set(efl_added, "Efl Ui Text Item Factory"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
bx = efl_add(EFL_UI_BOX_CLASS, win);
efl_content_set(win, bx);
en = efl_add(EFL_UI_TEXT_CLASS, bx,
efl_text_multiline_set(efl_added, EINA_TRUE));
factories[FACTORY_NONE].name = "None (Fallback)";
factories[FACTORY_NONE].item_factory = NULL;
factories[FACTORY_IMAGE].name = "Image Factory";
factories[FACTORY_IMAGE].item_factory =
efl_add(EFL_UI_TEXT_FACTORY_IMAGES_CLASS, en);
factories[FACTORY_EMOTICON].name = "Emoticon Factory";
factories[FACTORY_EMOTICON].item_factory =
efl_add(EFL_UI_TEXT_FACTORY_EMOTICONS_CLASS, en);
// Test assigning file path source
snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", elm_app_data_dir_get());
efl_ui_text_factory_images_matches_add(factories[FACTORY_IMAGE].item_factory,
images[0], buf, NULL);
snprintf(buf, sizeof(buf), "%s/images/logo.png", elm_app_data_dir_get());
efl_ui_text_factory_images_matches_add(factories[FACTORY_IMAGE].item_factory,
images[1], buf, NULL);
snprintf(buf, sizeof(buf), "%s/images/mystrale.jpg", elm_app_data_dir_get());
efl_ui_text_factory_images_matches_add(factories[FACTORY_IMAGE].item_factory,
images[2], buf, NULL);
// Open EET source w/ key
snprintf(buf, sizeof(buf), "%s/images/image_items.eet", elm_app_data_dir_get());
f = eina_file_open(buf, EINA_FALSE);
if (f)
{
efl_ui_text_factory_images_matches_mmap_add(
factories[FACTORY_IMAGE].item_factory,
"eet_rock", f, "rock");
efl_ui_text_factory_images_matches_mmap_add(
factories[FACTORY_IMAGE].item_factory,
"eet_plant", f, "plant");
eina_file_close(f);
}
else
{
printf("Error loading test file. Please review test.");
}
printf("Added Efl.Ui.Text object\n");
efl_text_set(en, "Hello world! Goodbye world! This is a test text for the"
" new UI Text widget.\xE2\x80\xA9This is the next paragraph.\nThis"
" is the next line.\nThis is Yet another line! Line and paragraph"
" separators are actually different!");
efl_text_font_set(en, "Sans", 14);
efl_text_normal_color_set(en, 255, 255, 255, 255);
main_cur = efl_text_interactive_main_cursor_get(en);
cur = efl_ui_text_cursor_create(en);
efl_text_cursor_position_set(cur, 2);
efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(cur), "emoticon/happy", "size=32x32");
efl_text_cursor_position_set(cur, 50);
snprintf(buf, sizeof(buf), "file://%s/images/sky_01.jpg", elm_app_data_dir_get());
efl_text_cursor_item_insert(en, efl_text_cursor_handle_get(cur), buf, "size=32x32");
efl_text_cursor_position_set(main_cur, 5);
efl_text_interactive_editable_set(en, EINA_TRUE);
efl_ui_text_scrollable_set(en, EINA_TRUE);
efl_pack(bx, en);
elm_object_focus_set(en, EINA_TRUE);
bx2 = efl_add(EFL_UI_BOX_CLASS, bx);
efl_gfx_hint_weight_set(bx2, EFL_GFX_HINT_EXPAND, EFL_GFX_HINT_EXPAND);
efl_ui_layout_orientation_set(bx2, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
bt = efl_add(EFL_UI_BUTTON_CLASS, bx2);
efl_text_set(bt, "Image");
efl_event_callback_add(bt, EFL_INPUT_EVENT_CLICKED, _on_factory_bt_image_clicked, en);
efl_gfx_hint_weight_set(bt, EFL_GFX_HINT_EXPAND, 0.0);
efl_pack(bx2, bt);
elm_object_focus_allow_set(bt, EINA_FALSE);
bt = efl_add(EFL_UI_BUTTON_CLASS, bx2);
efl_text_set(bt, "Emoticon");
efl_event_callback_add(bt, EFL_INPUT_EVENT_CLICKED, _on_factory_bt_emoticon_clicked, en);
efl_gfx_hint_weight_set(bt, EFL_GFX_HINT_EXPAND, 0.0);
efl_pack(bx2, bt);
elm_object_focus_allow_set(bt, EINA_FALSE);
bt = efl_add(EFL_UI_BUTTON_CLASS, bx2);
efl_text_set(bt, "Factory");
efl_event_callback_add(bt, EFL_INPUT_EVENT_CLICKED, _on_factory_bt_factory_clicked, en);
efl_gfx_hint_weight_set(bt, EFL_GFX_HINT_EXPAND, 0.0);
efl_pack(bx2, bt);
elm_object_focus_allow_set(bt, EINA_FALSE);
efl_pack(bx, bx2);
efl_gfx_entity_size_set(win, EINA_SIZE2D(480, 320));
}

View File

@ -70,7 +70,7 @@ typedef struct tm Efl_Time;
typedef struct _Efl_Text_Cursor_Handle Efl_Text_Cursor_Handle;
typedef struct _Efl_Text_Cursor_Handle _Efl_Text_Cursor_Handle;
typedef struct _Efl_Text_Annotate_Annotation Efl_Text_Annotate_Annotation;
typedef struct _Efl_Text_Attribute_Handle Efl_Text_Attribute_Handle;
#include "interfaces/efl_types.eot.h"
@ -211,7 +211,6 @@ typedef Efl_Gfx_Path_Command_Type Efl_Gfx_Path_Command;
#include "interfaces/efl_text_font.eo.h"
#include "interfaces/efl_text_style.eo.h"
#include "interfaces/efl_text_format.eo.h"
#include "interfaces/efl_text_annotate.eo.h"
#include "interfaces/efl_text_markup.eo.h"
#include "interfaces/efl_text_markup_util.eo.h"

View File

@ -24,7 +24,6 @@
#include "interfaces/efl_text_font.eo.c"
#include "interfaces/efl_text_style.eo.c"
#include "interfaces/efl_text_format.eo.c"
#include "interfaces/efl_text_annotate.eo.c"
#include "interfaces/efl_text_markup.eo.c"
#include "interfaces/efl_gfx_entity.eo.c"

View File

@ -1,137 +0,0 @@
import efl_text_types;
interface @beta Efl.Text_Annotate {
[[Cursor API
]]
c_prefix: efl_text;
methods {
// Annotation
@property annotation {
[[A new format for $annotation.
This will replace the format applied by $annotation with $format.
Assumes that $annotation is a handle for an existing annotation,
i.e. one that was added using @.annotation_insert to this object.
Otherwise, this will fail and return $false.
]]
set {
return: bool; [[$true on success, $false otherwise.]]
}
get {
}
keys {
annotation: ptr(Efl.Text_Annotate_Annotation); [[Given annotation]]
}
values {
format: string; [[The new format for the given annotation]]
}
}
range_annotations_get @const {
[[Returns an iterator of all the handles in a range.
]]
params {
@in start: ptr(const(Efl.Text_Cursor_Handle)); [[Start of range]]
@in end: ptr(const(Efl.Text_Cursor_Handle)); [[End of range]]
}
return: iterator<ptr(Efl.Text_Annotate_Annotation)> @move; [[Handle of the Annotation]]
}
annotation_insert {
[[Inserts an annotation format in a specified range [$start, $end - 1].
The $format will be applied to the given range, and the $annotation
handle will be returned for further handling.
]]
params {
@in start: ptr(Efl.Text_Cursor_Handle); [[Start of range]]
@in end: ptr(Efl.Text_Cursor_Handle); [[End of range]]
@in format: string; [[Annotation format]]
}
return: ptr(Efl.Text_Annotate_Annotation); [[Handle of inserted annotation]]
}
annotation_del {
[[Deletes given annotation.
All formats applied by $annotation will be removed and it will be
deleted.
]]
params {
@in annotation: ptr(Efl.Text_Annotate_Annotation); [[Annotation to be
removed]]
}
return: bool; [[$true on success, $false otherwise.]]
}
annotation_positions_get {
[[Sets given cursors to the start and end positions of the annotation.
The cursors $start and $end will be set to the start and end
positions of the given annotation $annotation.
]]
params {
@in annotation: ptr(const(Efl.Text_Annotate_Annotation)); [[Annotation
handle to query]]
@in start: ptr(Efl.Text_Cursor_Handle); [[Cursor to be set to the start
position of the annotation in the text]]
@in end: ptr(Efl.Text_Cursor_Handle); [[Cursor to be set to the end
position of the annotation in the text]]
}
}
annotation_is_item {
[[Whether this is an "item" type of annotation. Should be used before
querying the annotation's geometry, as only "item" annotations have
a geometry.
see @.cursor_item_insert
see @.item_geometry_get
]]
params {
annotation: ptr(Efl.Text_Annotate_Annotation); [[Given annotation]]
}
return: bool; [[$true if given annotation is an object item, $false otherwise]]
}
item_geometry_get {
[[Queries a given object item for its geometry.
Note that the provided annotation should be an object item type.
]]
params {
@in an: ptr(const(Efl.Text_Annotate_Annotation)); [[Given annotation to query]]
@out x: int; [[X coordinate of the annotation]]
@out y: int; [[Y coordinate of the annotation]]
@out w: int; [[Width of the annotation]]
@out h: int; [[Height of the annotation]]
}
return: bool; [[$true if given annotation is an object item, $false otherwise]]
}
// Cursor
@property cursor_item_annotation {
[[The object-item annotation at the cursor's position.]]
get {
}
values {
annotation: ptr(Efl.Text_Annotate_Annotation); [[Annotation]]
}
keys {
cur: ptr(Efl.Text_Cursor_Handle); [[Cursor object]]
}
}
cursor_item_insert {
[[Inserts a object item at specified position.
This adds a placeholder to be queried by higher-level code,
which in turn place graphics on top of it. It essentially places an
OBJECT REPLACEMENT CHARACTER and set a special annotation to it.
]]
params {
cur: ptr(Efl.Text_Cursor_Handle); [[Cursor object]]
@in item: string; [[Item key to be used in higher-up
code to query and decided what image, emoticon
etc. to embed.]]
@in format: string; [[Size format of the inserted item.
This hints how to size the item in the text.]]
}
return: ptr(Efl.Text_Annotate_Annotation); [[The annotation handle of the
inserted item.]]
}
}
}

View File

@ -22,6 +22,4 @@ struct @beta Efl.Ui.Text_Change_Info {
merge: bool; [[$true if can be merged with the previous one. Used for example with insertion when something is already selected]]
}
type @extern @beta Efl.Text_Annotate_Annotation: __undefined_type; [[EFL text annotations data structure]]
struct @beta Efl.Text_Cursor_Handle; [[Opaque handle for Text cursors.]]
struct @extern @beta Efl.Text_Attribute_Handle; [[EFL text annotations data structure]]

View File

@ -44,7 +44,6 @@ pub_eo_files = [
'efl_text_font.eo',
'efl_text_style.eo',
'efl_text_format.eo',
'efl_text_annotate.eo',
'efl_text_markup.eo',
'efl_text_markup_util.eo',
'efl_gfx_stack.eo',

View File

@ -4,6 +4,7 @@
#include "elm_priv.h"
#include "efl_ui_internal_text_interactive.h"
#include "efl_canvas_text_internal.h"
#define MY_CLASS EFL_UI_INTERNAL_TEXT_INTERACTIVE_CLASS

View File

@ -153,7 +153,7 @@ struct _Anchor
{
Eo *obj;
char *name;
Efl_Text_Annotate_Annotation *annotation;
Efl_Text_Attribute_Handle *annotation;
Eina_List *rects;
int gen;
Eina_Bool item : 1;
@ -3180,13 +3180,12 @@ _efl_ui_text_efl_access_text_range_extents_get(const Eo *obj, Efl_Ui_Text_Data *
}
static Efl_Access_Text_Attribute*
_textblock_node_format_to_atspi_text_attr(const Eo *obj,
Efl_Text_Annotate_Annotation *annotation)
_textblock_node_format_to_atspi_text_attr(Efl_Text_Attribute_Handle *annotation)
{
Efl_Access_Text_Attribute *ret;
const char *txt;
txt = efl_text_annotation_get(obj, annotation);
txt = efl_text_attribute_factory_attribute_get(annotation);
if (!txt) return NULL;
ret = calloc(1, sizeof(Efl_Access_Text_Attribute));
@ -3202,34 +3201,35 @@ _textblock_node_format_to_atspi_text_attr(const Eo *obj,
EOLIAN static Eina_Bool
_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)
{
Evas_Textblock_Cursor *cur1, *cur2;
Efl_Text_Cursor *cur1, *cur2;
Efl_Access_Text_Attribute *attr;
Eina_Iterator *annotations;
Efl_Text_Annotate_Annotation *an;
Efl_Text_Attribute_Handle *an;
cur1 = evas_object_textblock_cursor_new(obj);
Eo *mobj = (Eo *)obj;
cur1 = efl_ui_text_cursor_create(mobj);
if (!cur1) return EINA_FALSE;
cur2 = evas_object_textblock_cursor_new(obj);
cur2 = efl_ui_text_cursor_create(mobj);
if (!cur2)
{
evas_textblock_cursor_free(cur1);
efl_del(cur1);
return EINA_FALSE;
}
evas_textblock_cursor_pos_set(cur1, *start_offset);
evas_textblock_cursor_pos_set(cur2, *end_offset);
efl_text_cursor_position_set(cur1, *start_offset);
efl_text_cursor_position_set(cur2, *end_offset);
annotations = efl_text_range_annotations_get(obj, cur1, cur2);
annotations = efl_text_attribute_factory_range_attributes_get(cur1, cur2);
evas_textblock_cursor_free(cur1);
evas_textblock_cursor_free(cur2);
efl_del(cur1);
efl_del(cur2);
if (!annotations) return EINA_FALSE;
EINA_ITERATOR_FOREACH(annotations, an)
{
attr = _textblock_node_format_to_atspi_text_attr(obj, an);
attr = _textblock_node_format_to_atspi_text_attr(an);
if (!attr) continue;
if (!strcmp(attr->name, attr_name))
{
@ -3247,35 +3247,35 @@ _efl_ui_text_efl_access_text_attribute_get(const Eo *obj, Efl_Ui_Text_Data *_pd
EOLIAN static Eina_List*
_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)
{
Evas_Textblock_Cursor *cur1, *cur2;
Efl_Text_Cursor *cur1, *cur2;
Eina_List *ret = NULL;
Efl_Access_Text_Attribute *attr;
Eina_Iterator *annotations;
Efl_Text_Annotate_Annotation *an;
cur1 = evas_object_textblock_cursor_new(obj);
Efl_Text_Attribute_Handle *an;
Eo *mobj = (Eo *)obj;
cur1 = efl_ui_text_cursor_create(mobj);
if (!cur1) return NULL;
cur2 = evas_object_textblock_cursor_new(obj);
cur2 = efl_ui_text_cursor_create(mobj);
if (!cur2)
{
evas_textblock_cursor_free(cur1);
efl_del(cur1);
return NULL;
}
evas_textblock_cursor_pos_set(cur1, *start_offset);
evas_textblock_cursor_pos_set(cur2, *end_offset);
efl_text_cursor_position_set(cur1, *start_offset);
efl_text_cursor_position_set(cur2, *end_offset);
annotations = efl_text_range_annotations_get(obj, cur1, cur2);
annotations = efl_text_attribute_factory_range_attributes_get(cur1, cur2);
evas_textblock_cursor_free(cur1);
evas_textblock_cursor_free(cur2);
efl_del(cur1);
efl_del(cur2);
if (!annotations) return NULL;
EINA_ITERATOR_FOREACH(annotations, an)
{
attr = _textblock_node_format_to_atspi_text_attr(obj, an);
attr = _textblock_node_format_to_atspi_text_attr(an);
if (!attr) continue;
ret = eina_list_append(ret, attr);
}
@ -3291,7 +3291,7 @@ _efl_ui_text_efl_access_text_default_attributes_get(const Eo *obj, Efl_Ui_Text_D
Efl_Access_Text_Attribute *attr;
Efl_Text_Cursor *start, *end;
Eina_Iterator *annotations;
Efl_Text_Annotate_Annotation *an;
Efl_Text_Attribute_Handle *an;
/* Retrieve all annotations in the text. */
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
efl_text_cursor_move(start, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_FIRST);
efl_text_cursor_move(end, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_LAST);
annotations = efl_text_range_annotations_get(obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end));
annotations = efl_text_attribute_factory_range_attributes_get(start, end);
EINA_ITERATOR_FOREACH(annotations, an)
{
attr = _textblock_node_format_to_atspi_text_attr(obj, an);
attr = _textblock_node_format_to_atspi_text_attr(an);
if (!attr) continue;
ret = eina_list_append(ret, attr);
}
@ -3659,20 +3659,20 @@ _anchor_format_parse(const char *item)
}
static Anchor *
_anchor_get(Eo *obj, Efl_Ui_Text_Data *sd, Efl_Text_Annotate_Annotation *an)
_anchor_get(Eo *obj, Efl_Ui_Text_Data *sd, Efl_Text_Attribute_Handle *an)
{
Anchor *anc;
Eina_List *i;
const char *str;
str = efl_text_annotation_get(obj, an);
str = efl_text_attribute_factory_attribute_get(an);
EINA_LIST_FOREACH(sd->anchors, i, anc)
{
if (anc->annotation == an) break;
}
if (!anc && (efl_text_annotation_is_item(obj, an) || !strncmp(str, "a ", 2)))
if (!anc && (efl_text_attribute_factory_attribute_is_item(an) || !strncmp(str, "a ", 2)))
{
const char *p;
@ -3681,7 +3681,7 @@ _anchor_get(Eo *obj, Efl_Ui_Text_Data *sd, Efl_Text_Annotate_Annotation *an)
{
anc->obj = obj;
anc->annotation = an;
anc->item = efl_text_annotation_is_item(obj, an);
anc->item = efl_text_attribute_factory_attribute_is_item(an);
p = strstr(str, "href=");
if (p)
{
@ -3705,7 +3705,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
Eina_Iterator *it;
Eina_Position2D off;
Efl_Text_Cursor *start, *end;
Efl_Text_Annotate_Annotation *an;
Efl_Text_Attribute_Handle *an;
Eina_List *i, *ii;
Anchor *anc;
@ -3723,7 +3723,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
efl_text_cursor_move(start, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_FIRST);
efl_text_cursor_move(end, EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_LAST);
it = efl_text_range_annotations_get(obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end));
it = efl_text_attribute_factory_range_attributes_get(start, end);
efl_del(start);
efl_del(end);
@ -3765,8 +3765,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
}
rect = eina_list_data_get(anc->rects);
efl_text_item_geometry_get(sd->text_obj,
anc->annotation, &cx, &cy, &cw, &ch);
efl_text_attribute_factory_item_geometry_get(anc->annotation, &cx, &cy, &cw, &ch);
efl_gfx_entity_size_set(rect->obj, EINA_SIZE2D(cw, ch));
efl_gfx_entity_position_set(rect->obj,
EINA_POSITION2D(off.x + cx, off.y + cy));
@ -3780,8 +3779,7 @@ _anchors_update(Eo *obj, Efl_Ui_Text_Data *sd)
size_t count;
start = efl_ui_text_cursor_create(obj);
end = efl_ui_text_cursor_create(obj);
efl_text_annotation_positions_get(obj, anc->annotation,
efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end));
efl_text_attribute_factory_attribute_cursors_get(anc->annotation, start, end);
range = efl_text_cursor_range_geometry_get(start, end);
count = eina_list_count(eina_iterator_container_get(range));

View File

@ -84,6 +84,7 @@ extern "C" {
*/
#include <canvas/efl_canvas_snapshot.eo.h>
#include <canvas/efl_text_cursor.eo.h>
#include <canvas/efl_text_attribute_factory.eo.h>
#include <canvas/efl_canvas_text.eo.h>
#include <canvas/efl_canvas_text_factory.eo.h>
#include <canvas/efl_canvas_vg_node.eo.h>

View File

@ -155,6 +155,7 @@ struct _Efl_Canvas_Object_Animation_Event
* @{
*/
#include "canvas/efl_text_cursor.eo.h"
#include "canvas/efl_text_attribute_factory.eo.h"
#include "canvas/efl_canvas_text.eo.h"
#include "canvas/efl_canvas_text_factory.eo.h"
/**

View File

@ -318,6 +318,17 @@ EWAPI extern const Efl_Event_Description _EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED
*/
EAPI Eina_Bool evas_textblock_cursor_at_cluster_as_single_glyph(Evas_Textblock_Cursor *cur,Eina_Bool forward);
/*Attribute Factory Internal function*/
EAPI const char * efl_text_attribute_factory_attribute_get(Efl_Text_Attribute_Handle *annotation);
EAPI Eina_Iterator * efl_text_attribute_factory_range_attributes_get(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end);
EAPI void efl_text_attribute_factory_attribute_cursors_get(const Efl_Text_Attribute_Handle *handle, Efl_Text_Cursor *start, Efl_Text_Cursor *end);
EAPI void efl_text_attribute_factory_remove(Efl_Text_Attribute_Handle *annotation);
EAPI Eina_Bool efl_text_attribute_factory_attribute_is_item(Efl_Text_Attribute_Handle *annotation);
EAPI Eina_Bool efl_text_attribute_factory_item_geometry_get(const Efl_Text_Attribute_Handle *annotation, int *x, int *y, int *w, int *h);
#ifdef __cplusplus
}
#endif

View File

@ -3,7 +3,7 @@ import efl_text_types;
class @beta Efl.Canvas.Text extends Efl.Canvas.Object implements Efl.Text,
Efl.Canvas.Filter.Internal, Efl.Text_Font,
Efl.Text_Style, Efl.Text_Format,
Efl.Text_Annotate, Efl.Text_Markup, Efl.Ui.I18n
Efl.Text_Markup, Efl.Ui.I18n
{
[[Efl canvas text class]]
methods {
@ -236,15 +236,6 @@ class @beta Efl.Canvas.Text extends Efl.Canvas.Object implements Efl.Text,
Efl.Text_Format.tabstops { get; set; }
Efl.Text_Format.password { get; set; }
Efl.Text_Format.replacement_char { get; set; }
Efl.Text_Annotate.annotation { set; get; }
Efl.Text_Annotate.range_annotations_get;
Efl.Text_Annotate.annotation_insert;
Efl.Text_Annotate.annotation_del;
Efl.Text_Annotate.annotation_is_item;
Efl.Text_Annotate.item_geometry_get;
Efl.Text_Annotate.annotation_positions_get;
Efl.Text_Annotate.cursor_item_annotation { get; }
Efl.Text_Annotate.cursor_item_insert;
Efl.Text_Markup.markup { set; get; }
Efl.Gfx.Entity.scale { set; }
}

View File

@ -83,10 +83,10 @@ typedef struct _Evas_Object_Textblock_Format Evas_Object_Textblock_Format;
typedef struct _Evas_Textblock_Selection_Iterator Evas_Textblock_Selection_Iterator;
/**
* @internal
* @typedef Efl_Text_Annotate_Annotation_Iterator
* @typedef Efl_Text_Attribute_Handle_Iterator
* A textblock annotation iterator.
*/
typedef struct _Efl_Text_Annotate_Annotation_Iterator Efl_Text_Annotate_Annotation_Iterator;
typedef struct _Efl_Text_Attribute_Handle_Iterator Efl_Text_Attribute_Handle_Iterator;
/**
* @internal
* @typedef Efl_Canvas_Text_Filter
@ -143,7 +143,7 @@ struct _Evas_Textblock_Node_Format
const char *format; /**< Cached, parsed and translated version of orig_format. */
const char *orig_format; /**< Original format information. */
Evas_Object_Textblock_Node_Text *text_node; /**< The text node it's pointing to. */
Efl_Text_Annotate_Annotation *annotation; /**< Pointer to this node's annotation handle (if exists). */
Efl_Text_Attribute_Handle *annotation; /**< Pointer to this node's annotation handle (if exists). */
size_t offset; /**< Offset from the last format node of the same text. */
struct {
unsigned char l, r, t, b;
@ -166,8 +166,17 @@ struct _Efl_Text_Cursor_Handle
Eina_Bool changed : 1;
};
struct _Efl_Text_Attribute_Handle
{
EINA_INLIST;
Evas_Object *obj;
Evas_Object_Textblock_Node_Format *start_node, *end_node;
Eina_Bool is_item : 1; /**< indicates it is an item/object placeholder */
};
void evas_textblock_cursor_line_jump_by(Efl_Text_Cursor_Handle *cur, int by);
int _cursor_text_append(Efl_Text_Cursor_Handle *cur, const char *text);
void evas_textblock_async_block(Evas_Object *eo_object);
// 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);
// Used in Efl.Text.Cursor, where multible objects can have same handle.
void
evas_textblock_cursor_unref(Efl_Text_Cursor_Handle *cursor, Eo * cursor_obj);
void _evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb);
/*Annoation Functions*/
/**
* @internal
* Returns the value of the current data of list node,
* and goes to the next list node.
*
* @param it the iterator.
* @param data the data of the current list node.
* @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
*/
Eina_Bool
_evas_textblock_annotation_iterator_next(Efl_Text_Attribute_Handle_Iterator *it, void **data);
/**
* @internal
* Frees the annotation iterator.
* @param it the iterator to free
* @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
*/
void
_evas_textblock_annotation_iterator_free(Efl_Text_Attribute_Handle_Iterator *it);
/**
* @internal
* Creates newly allocated iterator associated to a list.
* @param list The list.
* @return If the memory cannot be allocated, NULL is returned.
* Otherwise, a valid iterator is returned.
*/
Eina_Iterator *
_evas_textblock_annotation_iterator_new(Eina_List *list);
void
_textblock_cursor_pos_at_fnode_set(Efl_Text_Cursor_Handle *cur,
Evas_Object_Textblock_Node_Format *fnode);
Eina_Bool
_evas_textblock_annotations_set(Evas_Object *eo_obj,
Efl_Text_Attribute_Handle *an,
Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
const char *format, Eina_Bool is_item);
void
_evas_textblock_annotation_remove(Evas_Object *eo_obj, Efl_Canvas_Text_Data *o,
Efl_Text_Attribute_Handle *an, Eina_Bool remove_nodes, Eina_Bool invalidate);
void
_evas_textblock_annotations_clear(const Evas_Object *eo_obj);
Efl_Text_Attribute_Handle *
_evas_textblock_annotations_insert(Eo *eo_obj,
Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
const char *format, Eina_Bool is_item);
Eina_Inlist *
_evas_textblock_annotations_get(Evas_Object *o);
void
_evas_textblock_annotations_node_format_remove(Evas_Object *o, Evas_Object_Textblock_Node_Format *n, int visual_adjustment);
void
_evas_textblock_relayout_if_needed(Evas_Object *o);
#ifdef EAPI
# undef EAPI
@ -213,7 +292,24 @@ evas_textblock_cursor_unref(Efl_Text_Cursor_Handle *cursor, Eo * cursor_obj);
*/
EAPI void efl_text_cursor_text_object_set(Eo *cursor, Eo *canvas_text_obj, Eo *text_obj);
/**
* Internally sets cursor handle(legacy textblock cursor) into cursor object.
*
* @param obj the cursor object.
* @param handle the text cursor handle.
*/
EAPI void efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Handle *handle);
/**
* Internally gets cursor handle(legacy textblock cursor) from cursor object.
*
* @param obj the cursor object.
* @return the internal text cursor handle.
*/
EAPI Efl_Text_Cursor_Handle *efl_text_cursor_handle_get(const Eo *obj);
#undef EAPI
#define EAPI
#endif
#endif//#ifndef _EFL_CANVAS_TEXT_INTERNAL_H

View File

@ -0,0 +1,133 @@
//#define EFL_BETA_API_SUPPORT
#include "evas_common_private.h"
#include "evas_private.h"
#include "efl_canvas_text_internal.h"
#include "efl_text_cursor.eo.h"
#define MY_CLASS EFL_TEXT_ATTRIBUTE_FACTORY_CLASS
typedef struct
{
} Efl_Text_Attribute_Factory_Data;
EOLIAN static void
_efl_text_attribute_factory_attribute_insert(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end, const char *format)
{
EINA_SAFETY_ON_TRUE_RETURN(!efl_text_cursor_handle_get(start) ||
!efl_text_cursor_handle_get(end) ||
efl_text_cursor_handle_get(start)->obj != efl_text_cursor_handle_get(end)->obj);
Eo *eo_obj= efl_text_cursor_handle_get(start)->obj;
evas_textblock_async_block(eo_obj);
_evas_textblock_annotations_insert(eo_obj, efl_text_cursor_handle_get(start), efl_text_cursor_handle_get(end), format,
EINA_FALSE);
efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
}
EOLIAN static unsigned int
_efl_text_attribute_factory_attribute_clear(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end)
{
unsigned int ret = 0;
Eina_Iterator *annotations;
Efl_Text_Attribute_Handle *an;
annotations = efl_text_attribute_factory_range_attributes_get(start, end);
if (!annotations) return ret;
EINA_ITERATOR_FOREACH(annotations, an)
{
ret++;
efl_text_attribute_factory_remove(an);
}
eina_iterator_free(annotations);
return ret;
}
const char *
efl_text_attribute_factory_attribute_get(Efl_Text_Attribute_Handle *annotation)
{
EINA_SAFETY_ON_TRUE_RETURN_VAL(!annotation || !(annotation->obj), NULL);
return (annotation->start_node ? annotation->start_node->format : NULL);
}
Eina_Iterator *
efl_text_attribute_factory_range_attributes_get(const Efl_Text_Cursor *start, const Efl_Text_Cursor *end)
{
Eina_List *lst = NULL;
Efl_Text_Attribute_Handle *it;
EINA_SAFETY_ON_TRUE_RETURN_VAL(!efl_text_cursor_handle_get(start) ||
!efl_text_cursor_handle_get(end) ||
efl_text_cursor_handle_get(start)->obj != efl_text_cursor_handle_get(end)->obj, NULL);
Eina_Inlist *annotations = _evas_textblock_annotations_get(efl_text_cursor_handle_get(start)->obj);
EINA_INLIST_FOREACH(annotations, it)
{
Efl_Text_Cursor_Handle start2, end2;
_evas_textblock_cursor_init(&start2, efl_text_cursor_handle_get(start)->obj);
_evas_textblock_cursor_init(&end2, efl_text_cursor_handle_get(start)->obj);
if (!it->start_node || !it->end_node) continue;
_textblock_cursor_pos_at_fnode_set(&start2, it->start_node);
_textblock_cursor_pos_at_fnode_set(&end2, it->end_node);
evas_textblock_cursor_char_prev(&end2);
if (!((evas_textblock_cursor_compare(&start2, efl_text_cursor_handle_get(end)) > 0) ||
(evas_textblock_cursor_compare(&end2, efl_text_cursor_handle_get(start)) < 0)))
{
lst = eina_list_append(lst, it);
}
}
return _evas_textblock_annotation_iterator_new(lst);
}
void
efl_text_attribute_factory_attribute_cursors_get(const Efl_Text_Attribute_Handle *handle, Efl_Text_Cursor *start, Efl_Text_Cursor *end)
{
EINA_SAFETY_ON_TRUE_RETURN (!handle || !(handle->obj));
efl_text_cursor_text_object_set(start, handle->obj, handle->obj);
efl_text_cursor_text_object_set(end, handle->obj, handle->obj);
_textblock_cursor_pos_at_fnode_set(efl_text_cursor_handle_get(start), handle->start_node);
_textblock_cursor_pos_at_fnode_set(efl_text_cursor_handle_get(end), handle->end_node);
}
void
efl_text_attribute_factory_remove(Efl_Text_Attribute_Handle *annotation)
{
EINA_SAFETY_ON_TRUE_RETURN (!annotation || !(annotation->obj));
evas_textblock_async_block(annotation->obj);
_evas_textblock_annotation_remove(annotation->obj, NULL, annotation, EINA_TRUE, EINA_TRUE);
}
Eina_Bool
efl_text_attribute_factory_attribute_is_item(Efl_Text_Attribute_Handle *annotation)
{
EINA_SAFETY_ON_TRUE_RETURN_VAL(!annotation || !(annotation->obj), EINA_FALSE);
return annotation->is_item;
}
Eina_Bool
efl_text_attribute_factory_item_geometry_get(const Efl_Text_Attribute_Handle *annotation, int *x, int *y, int *w, int *h)
{
EINA_SAFETY_ON_TRUE_RETURN_VAL(!annotation || !(annotation->obj), EINA_FALSE);
Efl_Text_Cursor_Handle cur;
Eo *eo_obj = annotation->obj;
Evas_Object_Protected_Data *obj_data = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
evas_object_async_block(obj_data);
_evas_textblock_relayout_if_needed(eo_obj);
_evas_textblock_cursor_init(&cur, eo_obj);
_textblock_cursor_pos_at_fnode_set(&cur, annotation->start_node);
return evas_textblock_cursor_format_item_geometry_get(&cur, x, y, w, h);
}
#include "efl_text_attribute_factory.eo.c"

View File

@ -0,0 +1,37 @@
import efl_text_types;
abstract @beta Efl.Text.Attribute.Factory extends Efl.Object {
[[Attribute factory API to manage text attributes.
Use it to insert and remove style attributes (font, size, color, ...) using @Efl.Text.Cursor on EFL Widgets.
Attributes can be assigned to character ranges, selected using two @Efl.Text.Cursor instances.
Cursor instances are already bound to a text object so there's no need to provide it to this class.
Style is specified using format strings as described in Efl.Canvas.Text.style_set.
There is no need to instantiate this class. Use directly the @.attribute_insert and @.attribute_clear static methods.]]
methods {
attribute_insert @static {
[[Inserts an attribute format in a specified range [$start, $end - 1].
The $format will be applied to the given range.
The passed cursors must belong to same textObject, else insertion will be ignored.
Passed format parameter uses same format as style in Efl.Canvas.Text.style_set.
]]
params {
start: const(Efl.Text.Cursor); [[Start of range.]]
end: const(Efl.Text.Cursor); [[End of range.]]
format: string; [[Attribute format.]]
}
}
attribute_clear @static {
[[Clear(remove) attributes at specified range [$start, $end - 1].
]]
params {
start: const(Efl.Text.Cursor); [[Start of range.]]
end: const(Efl.Text.Cursor); [[End of range.]]
}
return: uint; [[Number of removed attributes.]]
}
}
}

View File

@ -406,9 +406,10 @@ _efl_text_cursor_range_delete(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Data *pd, Efl
evas_textblock_cursor_range_delete(pd->handle, efl_text_cursor_handle_get(cur2));
}
EOLIAN static void
_efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Data *pd, Efl_Text_Cursor_Handle *handle)
EAPI void
efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Handle *handle)
{
Efl_Text_Cursor_Data *pd = efl_data_scope_get(obj, MY_CLASS);
if (handle == pd->handle)
return;
@ -422,9 +423,10 @@ _efl_text_cursor_handle_set(Eo *obj, Efl_Text_Cursor_Data *pd, Efl_Text_Cursor_H
}
}
EOLIAN static Efl_Text_Cursor_Handle *
_efl_text_cursor_handle_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Data *pd)
EAPI Efl_Text_Cursor_Handle *
efl_text_cursor_handle_get(const Eo *obj)
{
Efl_Text_Cursor_Data *pd = efl_data_scope_get(obj, MY_CLASS);
return pd->handle;
}

View File

@ -215,19 +215,6 @@ class @beta Efl.Text.Cursor extends Efl.Object implements Efl.Duplicate{
}
}
@property handle {
[[This method should rarely be used by users. It gives you a lightweight handle to a cursor.
You can either replace the handle to change the object this is working on, or get it for caching
The handle is freed when the object is freed if set, but otherwise it remains under the control of the caller.]]
set { }
get { }
values {
handle: Efl.Text_Cursor_Handle @by_ref; [[The handle of the cursor object.]]
}
}
@property text_object {
[[The text object this cursor is associated with.]]
get { }

View File

@ -419,13 +419,6 @@ typedef struct _User_Style_Entry
Evas_Textblock_Style *st;
const char *key;
} User_Style_Entry;
struct _Efl_Text_Annotate_Annotation
{
EINA_INLIST;
Evas_Object *obj;
Evas_Object_Textblock_Node_Format *start_node, *end_node;
Eina_Bool is_item : 1; /**< indicates it is an item/object placeholder */
};
#define _FMT(x) (o->default_format.format.x)
#define _FMT_INFO(x) (o->default_format.info.x)
@ -461,7 +454,7 @@ struct _Evas_Object_Textblock
Eina_List *anchors_item;
Eina_List *obstacles;
Eina_List *hyphen_items; /* Hyphen items storage to free when clearing lines */
Efl_Text_Annotate_Annotation *annotations; /* All currently applied annotations on the text. */
Efl_Text_Attribute_Handle *annotations; /* All currently applied annotations on the text. */
int last_w, last_h;
struct {
int l, r, t, b;
@ -524,7 +517,7 @@ struct _Evas_Textblock_Selection_Iterator
Eina_List *current; /**< Current node in loop. */
};
struct _Efl_Text_Annotate_Annotation_Iterator
struct _Efl_Text_Attribute_Handle_Iterator
{
Eina_Iterator iterator; /**< Eina Iterator. */
Eina_List *list; /**< Head of list. */
@ -604,12 +597,9 @@ static void _evas_textblock_changed(Efl_Canvas_Text_Data *o, Evas_Object *eo_obj
static void _evas_textblock_invalidate_all(Efl_Canvas_Text_Data *o);
static void _evas_textblock_cursors_update_offset(const Efl_Text_Cursor_Handle *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset);
static 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);
static void _evas_textblock_annotations_clear(Efl_Canvas_Text_Data *o);
static void _evas_textblock_annotation_remove(Efl_Canvas_Text_Data *o, Efl_Text_Annotate_Annotation *an, Eina_Bool remove_nodes);
static Eina_Bool _evas_textblock_cursor_format_is_visible_get(const Efl_Text_Cursor_Handle *cur);
static void _evas_textblock_cursor_at_format_set(Efl_Text_Cursor_Handle *cur, const Evas_Object_Textblock_Node_Format *fmt);
static void _evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb);
static Evas_Filter_Program *_format_filter_program_get(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Format *fmt);
static 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);
#ifdef HAVE_HYPHEN
@ -619,7 +609,6 @@ static const char *_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o
static 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);
EAPI Eina_Bool evas_textblock_cursor_eol_get(const Evas_Textblock_Cursor *cur);
static void _evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb);
static Eina_Bool _evas_textblock_cursor_format_is_visible_get(const Efl_Text_Cursor_Handle *cur);
static 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);
static 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)
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
/* First, clear all annotations that may have spawned format nodes. */
_evas_textblock_annotations_clear(o);
_evas_textblock_annotations_clear(eo_obj);
while (o->text_nodes)
{
@ -6966,6 +6955,13 @@ _relayout_if_needed(const Evas_Object *eo_obj, Efl_Canvas_Text_Data *o)
return EINA_TRUE;
}
void
_evas_textblock_relayout_if_needed(Evas_Object *eo_obj)
{
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
_relayout_if_needed(eo_obj, o);
}
/**
* @internal
* 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
return previous_format;
}
static void
void
_evas_textblock_cursor_init(Efl_Text_Cursor_Handle *cur, const Evas_Object *tb)
{
memset(cur, 0, sizeof(Efl_Text_Cursor_Handle));
@ -10082,7 +10078,7 @@ _evas_textblock_node_format_remove_matching(Efl_Canvas_Text_Data *o,
if (_FORMAT_IS_CLOSER_OF(
fnode->orig_format, fstr + 1, fstr_len - 1))
{
Efl_Text_Annotate_Annotation *an = fmt->annotation;
Efl_Text_Attribute_Handle *an = fmt->annotation;
fnode = eina_list_data_get(i);
formats = eina_list_remove_list(formats, i);
@ -10092,7 +10088,7 @@ _evas_textblock_node_format_remove_matching(Efl_Canvas_Text_Data *o,
if (an)
{
_evas_textblock_annotation_remove(
o, an, EINA_FALSE);
NULL, o, an, EINA_FALSE, EINA_FALSE);
}
break;
}
@ -10190,6 +10186,13 @@ _evas_textblock_node_format_remove(Efl_Canvas_Text_Data *o, Evas_Object_Textbloc
_evas_textblock_node_format_free(o, n);
}
void
_evas_textblock_annotations_node_format_remove(Evas_Object *eo_obj, Evas_Object_Textblock_Node_Format *n, int visual_adjustment)
{
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
_evas_textblock_node_format_remove(o, n, visual_adjustment);
}
/**
* @internal
* 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)
return o->utf8;
}
void evas_textblock_async_block(Evas_Object *eo_obj)
{
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
ASYNC_BLOCK;
}
/**
* @internal
* 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)
* @param data the data of the current list node.
* @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
*/
static Eina_Bool
_evas_textblock_annotation_iterator_next(Efl_Text_Annotate_Annotation_Iterator *it, void **data)
Eina_Bool
_evas_textblock_annotation_iterator_next(Efl_Text_Attribute_Handle_Iterator *it, void **data)
{
if (!it->current)
return EINA_FALSE;
@ -15246,8 +15255,8 @@ _evas_textblock_annotation_iterator_next(Efl_Text_Annotate_Annotation_Iterator *
* @param it the iterator to free
* @return EINA_FALSE if unsuccessful. Otherwise, returns EINA_TRUE.
*/
static void
_evas_textblock_annotation_iterator_free(Efl_Text_Annotate_Annotation_Iterator *it)
void
_evas_textblock_annotation_iterator_free(Efl_Text_Attribute_Handle_Iterator *it)
{
EINA_MAGIC_SET(&it->iterator, 0);
it->current = NULL;
@ -15267,7 +15276,7 @@ _evas_textblock_annotation_iterator_new(Eina_List *list)
{
Evas_Textblock_Selection_Iterator *it;
it = calloc(1, sizeof(Efl_Text_Annotate_Annotation_Iterator));
it = calloc(1, sizeof(Efl_Text_Attribute_Handle_Iterator));
if (!it) return NULL;
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
@ -15283,24 +15292,24 @@ _evas_textblock_annotation_iterator_new(Eina_List *list)
return &it->iterator;
}
static void
_textblock_cursor_pos_at_fnode_set(const Eo *eo_obj EINA_UNUSED,
Efl_Text_Cursor_Handle *cur,
void
_textblock_cursor_pos_at_fnode_set(Efl_Text_Cursor_Handle *cur,
Evas_Object_Textblock_Node_Format *fnode)
{
cur->node = fnode->text_node;
cur->pos = _evas_textblock_node_format_pos_get(fnode);
}
static Eina_Bool
_textblock_annotation_set(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o,
Efl_Text_Annotate_Annotation *an,
Eina_Bool
_evas_textblock_annotations_set(Eo *eo_obj,
Efl_Text_Attribute_Handle *an,
Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
const char *format, Eina_Bool is_item)
{
int len;
char *buf;
Evas_Textblock_Node_Format *fnode;
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
if (an->is_item)
{
@ -15332,60 +15341,20 @@ _textblock_annotation_set(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o,
return EINA_TRUE;
}
EOLIAN static const char *
_efl_canvas_text_efl_text_annotate_annotation_get(const Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o EINA_UNUSED,
Efl_Text_Annotate_Annotation *annotation)
Eina_Inlist *
_evas_textblock_annotations_get(Eo *eo_obj)
{
if (!annotation || (annotation->obj != eo_obj))
{
ERR("Used invalid handle or of a different object");
return NULL;
}
return (annotation->start_node ? annotation->start_node->format : NULL);
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
return (Eina_Inlist*)o->annotations;
}
EOLIAN static Eina_Bool
_efl_canvas_text_efl_text_annotate_annotation_set(Eo *eo_obj,
Efl_Canvas_Text_Data *o, Efl_Text_Annotate_Annotation *annotation,
const char *format)
void
_evas_textblock_annotation_remove(Eo *eo_obj, Efl_Canvas_Text_Data *o,
Efl_Text_Attribute_Handle *an, Eina_Bool remove_nodes, Eina_Bool invalidate)
{
ASYNC_BLOCK;
Efl_Text_Cursor_Handle start, end;
Eina_Bool ret = EINA_TRUE;
if (!o)
o = efl_data_scope_get(eo_obj, MY_CLASS);
if (!annotation || (annotation->obj != eo_obj))
{
ERR("Used invalid handle or of a different object");
return EINA_FALSE;
}
if (!annotation->start_node || !annotation->end_node) return EINA_FALSE;
if (!format || (format[0] == '\0')) return EINA_FALSE;
_evas_textblock_cursor_init(&start, eo_obj);
_evas_textblock_cursor_init(&end, eo_obj);
/* XXX: Not efficient but works and saves code */
_textblock_cursor_pos_at_fnode_set(eo_obj, &start, annotation->start_node);
_textblock_cursor_pos_at_fnode_set(eo_obj, &end, annotation->end_node);
_evas_textblock_node_format_remove(o, annotation->start_node, 0);
_evas_textblock_node_format_remove(o, annotation->end_node, 0);
if (!_textblock_annotation_set(eo_obj, o, annotation, &start, &end, format,
EINA_FALSE))
{
ret = EINA_FALSE;
}
return ret;
}
static void
_evas_textblock_annotation_remove(Efl_Canvas_Text_Data *o,
Efl_Text_Annotate_Annotation *an, Eina_Bool remove_nodes)
{
if (remove_nodes)
{
if (an->is_item)
@ -15393,64 +15362,53 @@ _evas_textblock_annotation_remove(Efl_Canvas_Text_Data *o,
/* Remove the OBJ character along with the cursor. */
Efl_Text_Cursor_Handle cur;
_evas_textblock_cursor_init(&cur, an->obj);
_textblock_cursor_pos_at_fnode_set(an->obj, &cur, an->start_node);
_textblock_cursor_pos_at_fnode_set(&cur, an->start_node);
evas_textblock_cursor_char_delete(&cur);
return; // 'an' should be deleted after char deletion.
}
_evas_textblock_node_format_remove(o, an->start_node, 0);
_evas_textblock_node_format_remove(o, an->end_node, 0);
}
o->annotations = (Efl_Text_Annotate_Annotation *)
o->annotations = (Efl_Text_Attribute_Handle *)
eina_inlist_remove(EINA_INLIST_GET(o->annotations),
EINA_INLIST_GET(an));
free(an);
if (invalidate)
{
o->format_changed = EINA_TRUE;
//XXX: It's a workaround. The underlying problem is that only new format
// nodes are checks when their respective text nodes are invalidated (see
// _format_changes_invalidate_text_nodes). Complete removal of the format
// nodes was not handled properly (as formats could only be removed via
// text changes e.g. deleting characters).
_evas_textblock_invalidate_all(o);
_evas_textblock_changed(o, eo_obj);
}
}
static void
_evas_textblock_annotations_clear(Efl_Canvas_Text_Data *o)
void
_evas_textblock_annotations_clear(const Eo *eo_obj)
{
Efl_Text_Annotate_Annotation *an;
Efl_Text_Attribute_Handle *an;
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
EINA_INLIST_FREE(o->annotations, an)
{
_evas_textblock_annotation_remove(o, an, EINA_TRUE);
_evas_textblock_annotation_remove(NULL, o, an, EINA_TRUE, EINA_FALSE);
}
}
EOLIAN static Eina_Bool
_efl_canvas_text_efl_text_annotate_annotation_del(Eo *eo_obj EINA_UNUSED,
Efl_Canvas_Text_Data *o, Efl_Text_Annotate_Annotation *annotation)
{
ASYNC_BLOCK;
if (!annotation || (annotation->obj != eo_obj))
{
ERR("Used invalid handle or of a different object");
return EINA_FALSE;
}
_evas_textblock_annotation_remove(o, annotation, EINA_TRUE);
o->format_changed = EINA_TRUE;
//XXX: It's a workaround. The underlying problem is that only new format
// nodes are checks when their respective text nodes are invalidated (see
// _format_changes_invalidate_text_nodes). Complete removal of the format
// nodes was not handled properly (as formats could only be removed via
// text changes e.g. deleting characters).
_evas_textblock_invalidate_all(o);
_evas_textblock_changed(o, eo_obj);
return EINA_TRUE;
}
static Efl_Text_Annotate_Annotation *
_textblock_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o,
Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
Efl_Text_Attribute_Handle *
_evas_textblock_annotations_insert(Eo *eo_obj, Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
const char *format, Eina_Bool is_item)
{
Efl_Text_Annotate_Annotation *ret = NULL;
Efl_Text_Attribute_Handle *ret = NULL;
Eina_Strbuf *buf;
Eina_Bool first = EINA_TRUE;
const char *item;
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
if (!format || (format[0] == '\0') ||
evas_textblock_cursor_compare(start, end) > 0)
@ -15489,15 +15447,15 @@ _textblock_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o,
format = eina_strbuf_string_get(buf);
if (format && (format[0] != '\0'))
{
ret = calloc(1, sizeof(Efl_Text_Annotate_Annotation));
ret = calloc(1, sizeof(Efl_Text_Attribute_Handle));
ret->obj = eo_obj;
o->annotations = (Efl_Text_Annotate_Annotation *)
o->annotations = (Efl_Text_Attribute_Handle *)
eina_inlist_append(EINA_INLIST_GET(o->annotations),
EINA_INLIST_GET(ret));
_textblock_annotation_set(eo_obj, o, ret, start, end, format, is_item);
_evas_textblock_annotations_set(eo_obj, ret, start, end, format, is_item);
ret->is_item = is_item;
_evas_textblock_changed(o, eo_obj);
}
@ -15507,123 +15465,6 @@ _textblock_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o,
return ret;
}
EOLIAN static Efl_Text_Annotate_Annotation *
_efl_canvas_text_efl_text_annotate_annotation_insert(Eo *eo_obj, Efl_Canvas_Text_Data *o,
Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end,
const char *format)
{
ASYNC_BLOCK;
Efl_Text_Annotate_Annotation *ret;
ret = _textblock_annotation_insert(eo_obj, o, start, end, format,
EINA_FALSE);
efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
return ret;
}
EOLIAN static Eina_Iterator *
_efl_canvas_text_efl_text_annotate_range_annotations_get(const Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED,
const Evas_Textblock_Cursor *start, const Evas_Textblock_Cursor *end)
{
Eina_List *lst = NULL;
Efl_Text_Annotate_Annotation *it;
EINA_INLIST_FOREACH(o->annotations, it)
{
Efl_Text_Cursor_Handle start2, end2;
_evas_textblock_cursor_init(&start2, eo_obj);
_evas_textblock_cursor_init(&end2, eo_obj);
if (!it->start_node || !it->end_node) continue;
_textblock_cursor_pos_at_fnode_set(eo_obj, &start2, it->start_node);
_textblock_cursor_pos_at_fnode_set(eo_obj, &end2, it->end_node);
evas_textblock_cursor_char_prev(&end2);
if (!((evas_textblock_cursor_compare(&start2, end) > 0) ||
(evas_textblock_cursor_compare(&end2, start) < 0)))
{
lst = eina_list_append(lst, it);
}
}
return _evas_textblock_annotation_iterator_new(lst);
}
EOLIAN static Efl_Text_Annotate_Annotation *
_efl_canvas_text_efl_text_annotate_cursor_item_insert(Eo *eo_obj,
Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Handle *cur,
const char *item, const char *format)
{
Eina_Strbuf *buf = eina_strbuf_new();
eina_strbuf_append_printf(buf, "%s href=%s", format, item);
Efl_Text_Annotate_Annotation *ret =
_textblock_annotation_insert(cur->obj, o, cur, cur,
eina_strbuf_string_get(buf), EINA_TRUE);
eina_strbuf_free(buf);
efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
return ret;
}
EOLIAN static Efl_Text_Annotate_Annotation *
_efl_canvas_text_efl_text_annotate_cursor_item_annotation_get(const Eo *eo_obj EINA_UNUSED,
Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Handle *cur)
{
Eina_Iterator *it;
Efl_Text_Annotate_Annotation *data, *ret = NULL;
it = efl_text_range_annotations_get(cur->obj,
cur, cur);
EINA_ITERATOR_FOREACH(it, data)
{
if (data->is_item)
{
ret = data;
break;
}
}
eina_iterator_free(it);
return ret;
}
EOLIAN static Eina_Bool
_efl_canvas_text_efl_text_annotate_annotation_is_item(Eo *eo_obj EINA_UNUSED,
Efl_Canvas_Text_Data *o EINA_UNUSED,
Efl_Text_Annotate_Annotation *annotation)
{
if (!annotation || (annotation->obj != eo_obj))
{
ERR("Used invalid handle or of a different object");
return EINA_FALSE;
}
return annotation->is_item;
}
EOLIAN static Eina_Bool
_efl_canvas_text_efl_text_annotate_item_geometry_get(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED,
const Efl_Text_Annotate_Annotation *an, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
{
Efl_Text_Cursor_Handle cur;
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
evas_object_async_block(obj);
_relayout_if_needed(eo_obj, o);
_evas_textblock_cursor_init(&cur, eo_obj);
_textblock_cursor_pos_at_fnode_set(eo_obj, &cur, an->start_node);
return _evas_textblock_cursor_format_item_geometry_get(&cur, cx, cy, cw, ch);
}
EOLIAN static void
_efl_canvas_text_efl_text_annotate_annotation_positions_get(Eo *eo_obj,
Efl_Canvas_Text_Data *o EINA_UNUSED,
const Efl_Text_Annotate_Annotation *annotation,
Efl_Text_Cursor_Handle *start, Efl_Text_Cursor_Handle *end)
{
_textblock_cursor_pos_at_fnode_set(eo_obj, start, annotation->start_node);
_textblock_cursor_pos_at_fnode_set(eo_obj, end, annotation->end_node);
}
static void
_canvas_text_format_changed(Eo *eo_obj, Efl_Canvas_Text_Data *o)
{

View File

@ -56,6 +56,7 @@ pub_eo_files = [
'efl_canvas_event_grabber.eo',
'efl_text_cursor.eo',
'efl_canvas_text.eo',
'efl_text_attribute_factory.eo',
'efl_canvas_object_animation.eo',
]
@ -208,7 +209,8 @@ evas_src += files([
'evas_canvas3d_node_callback.h',
'evas_canvas3d_eet.c',
'efl_canvas_object_animation.c',
'efl_text_cursor.c'
'efl_text_cursor.c',
'efl_text_attribute_factory.c'
])
evas_include_directories += include_directories('.')

View File

@ -37,6 +37,7 @@ static const char *style_buf =
Evas_Object *tb; \
Evas_Textblock_Style *st; \
Evas_Textblock_Cursor *cur; \
Efl_Text_Cursor *cur_obj; \
evas = EVAS_TEST_INIT_EVAS(); \
evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \
tb = evas_object_textblock_add(evas); \
@ -48,6 +49,9 @@ static const char *style_buf =
fail_if(strcmp(style_buf, evas_textblock_style_get(st))); \
evas_object_textblock_style_set(tb, st); \
cur = evas_object_textblock_cursor_new(tb); \
cur_obj =efl_canvas_text_cursor_create(tb);\
(void) cur_obj;\
(void) cur;\
do \
{ \
} \
@ -58,6 +62,7 @@ do \
{ \
evas_textblock_cursor_free(cur); \
evas_object_del(tb); \
efl_del(cur_obj); \
evas_textblock_style_free(st); \
evas_free(evas); \
} \
@ -4304,43 +4309,6 @@ EFL_START_TEST(evas_textblock_text_iface)
}
EFL_END_TEST;
static void
_test_check_annotation(Evas_Object *tb,
size_t start_pos, size_t end_pos,
size_t len, const char **formats)
{
Efl_Text_Annotate_Annotation *an;
Efl_Text_Cursor_Handle *start, *end;
start = evas_object_textblock_cursor_new(tb);
end = evas_object_textblock_cursor_new(tb);
evas_textblock_cursor_pos_set(start, start_pos);
evas_textblock_cursor_pos_set(end, end_pos);
Eina_Iterator *it =
efl_text_range_annotations_get(tb, start, end);
evas_textblock_cursor_free(start);
evas_textblock_cursor_free(end);
size_t i = 0;
EINA_ITERATOR_FOREACH(it, an)
{
const char *fmt = efl_text_annotation_get(tb,
an);
ck_assert_msg((i < len),
"No formats to check but current annotation is: %s\n", fmt);
ck_assert_str_eq(fmt, *formats);
formats++;
i++;
}
ck_assert_msg((i == len),
"Expected next format (index %lu): %s, but reached end of annotations\n",
i, *formats);
eina_iterator_free(it);
}
#define _COMP_STR(...) ((const char *[]) { __VA_ARGS__ })
#define _CREATE_PARAMS(X) (sizeof(X) / sizeof(X[0])), (X)
@ -4349,11 +4317,10 @@ _test_check_annotation(Evas_Object *tb,
EFL_START_TEST(evas_textblock_annotation)
{
START_TB_TEST();
Efl_Text_Annotate_Annotation *an, *an2;
Efl_Text_Cursor_Handle *start, *end;
Efl_Text_Cursor *start, *end;
start = evas_object_textblock_cursor_new(tb);
end = evas_object_textblock_cursor_new(tb);
start = efl_canvas_text_cursor_create(tb);
end = efl_canvas_text_cursor_create(tb);
const char *buf =
"This text will check annotation."
@ -4365,167 +4332,21 @@ EFL_START_TEST(evas_textblock_annotation)
efl_text_set(tb, buf);
/* Check some trivial cases */
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 3);
ck_assert(!efl_text_annotation_insert(tb, start, end, NULL));
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 3);
ck_assert(!efl_text_annotation_insert(tb, start, end, ""));
evas_textblock_cursor_pos_set(start, 1);
evas_textblock_cursor_pos_set(end, 0);
ck_assert(!efl_text_annotation_insert(tb, start, end, "color=#fff"));
/* Insert and check correct positions */
_test_check_annotation(tb, 0, 10, _COMP_PARAMS());
efl_text_cursor_position_set(start, 0);
efl_text_cursor_position_set(end, 3);
efl_text_attribute_factory_attribute_insert(start, end, "font_size=80");
efl_text_cursor_position_set(start, 1);
efl_text_cursor_position_set(end, 2);
efl_text_attribute_factory_attribute_insert(start, end, "font=arial");
efl_text_cursor_position_set(start, 2);
efl_text_cursor_position_set(end, 3);
efl_text_attribute_factory_attribute_insert(start, end, "color=#fff");
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 3);
efl_text_annotation_insert(tb, start, end, "font_weight=bold");
_test_check_annotation(tb, 0, 2, _COMP_PARAMS("font_weight=bold"));
_test_check_annotation(tb, 0, 2, _COMP_PARAMS("font_weight=bold"));
_test_check_annotation(tb, 4, 10, _COMP_PARAMS());
evas_textblock_cursor_pos_set(start, 50);
evas_textblock_cursor_pos_set(end, 60);
efl_text_annotation_insert(tb, start, end, "color=#0ff");
_test_check_annotation(tb, 0, 49, _COMP_PARAMS("font_weight=bold"));
_test_check_annotation(tb, 0, 50, _COMP_PARAMS("font_weight=bold", "color=#0ff"));
_test_check_annotation(tb, 0, 55, _COMP_PARAMS("font_weight=bold", "color=#0ff"));
_test_check_annotation(tb, 0, 59, _COMP_PARAMS("font_weight=bold", "color=#0ff"));
_test_check_annotation(tb, 40, 50, _COMP_PARAMS("color=#0ff"));
_test_check_annotation(tb, 40, 51, _COMP_PARAMS("color=#0ff"));
_test_check_annotation(tb, 40, 61, _COMP_PARAMS("color=#0ff"));
_test_check_annotation(tb, 59, 60, _COMP_PARAMS("color=#0ff"));
_test_check_annotation(tb, 60, 61, _COMP_PARAMS());
/* See that annotation's positions are updated as text is inserted */
efl_text_set(tb, "hello");
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 2);
an = efl_text_annotation_insert(tb, start, end, "color=#fff");
_test_check_annotation(tb, 2, 3, _COMP_PARAMS());
evas_textblock_cursor_pos_set(cur, 0);
evas_textblock_cursor_text_append(cur, "a");
_test_check_annotation(tb, 2, 3, _COMP_PARAMS("color=#fff"));
_test_check_annotation(tb, 3, 4, _COMP_PARAMS());
/* Replace annotations's format */
efl_text_annotation_set(tb, an, "font_size=14");
_test_check_annotation(tb, 2, 3, _COMP_PARAMS("font_size=14"));
_test_check_annotation(tb, 3, 4, _COMP_PARAMS());
efl_text_set(tb, "hello world");
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 2);
an = efl_text_annotation_insert(tb, start, end, "color=#fff");
evas_textblock_cursor_pos_set(start, 2);
evas_textblock_cursor_pos_set(end, 3);
an2 = efl_text_annotation_insert(tb, start, end, "font_size=14");
_test_check_annotation(tb, 0, 1, _COMP_PARAMS("color=#fff"));
_test_check_annotation(tb, 2, 3, _COMP_PARAMS("font_size=14"));
_test_check_annotation(tb, 0, 3, _COMP_PARAMS("color=#fff", "font_size=14"));
efl_text_annotation_set(tb, an, "font_size=10");
efl_text_annotation_set(tb, an2, "color=#000");
_test_check_annotation(tb, 2, 3, _COMP_PARAMS("color=#000"));
_test_check_annotation(tb, 0, 1, _COMP_PARAMS("font_size=10"));
_test_check_annotation(tb, 0, 3, _COMP_PARAMS("font_size=10", "color=#000"));
/* Delete annotations directly */
efl_text_set(tb, "hello world");
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 2);
an = efl_text_annotation_insert(tb, start, end, "color=#fff");
evas_textblock_cursor_pos_set(start, 3);
evas_textblock_cursor_pos_set(end, 4);
an2 = efl_text_annotation_insert(tb, start, end, "font_size=14");
efl_text_annotation_del(tb, an);
_test_check_annotation(tb, 0, 3, _COMP_PARAMS("font_size=14"));
efl_text_annotation_del(tb, an2);
_test_check_annotation(tb, 0, 3, _COMP_PARAMS());
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 1);
an = efl_text_annotation_insert(tb, start, end, "color=#fff");
_test_check_annotation(tb, 1, 3, _COMP_PARAMS());
_test_check_annotation(tb, 0, 0, _COMP_PARAMS("color=#fff"));
efl_text_annotation_del(tb, an);
_test_check_annotation(tb, 0, 0, _COMP_PARAMS());
/* Check blocking of "item formats" */
efl_text_set(tb, "hello world");
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 1);
efl_text_annotation_insert(tb, start, end, "ps");
_test_check_annotation(tb, 0, 1, _COMP_PARAMS());
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 1);
efl_text_annotation_insert(tb, start, end, "color=#fff");
_test_check_annotation(tb, 0, 1, _COMP_PARAMS("color=#fff"));
evas_textblock_cursor_pos_set(start, 2);
evas_textblock_cursor_pos_set(end, 3);
efl_text_annotation_insert(tb, start, end, "br");
evas_textblock_cursor_pos_set(start, 6);
evas_textblock_cursor_pos_set(end, 7);
efl_text_annotation_insert(tb, start, end, "item");
_test_check_annotation(tb, 0, 8, _COMP_PARAMS("color=#fff"));
/* Check "item" annotations */
efl_text_set(tb, "abcd");
evas_textblock_cursor_pos_set(cur, 4);
an = efl_text_cursor_item_insert(tb, cur, "", "size=16x16");
_test_check_annotation(tb, 4, 4, _COMP_PARAMS("size=16x16 href="));
/* Check that format is not extended if it's an "object item" */
evas_textblock_cursor_pos_set(cur, 5);
evas_textblock_cursor_text_prepend(cur, "a");
_test_check_annotation(tb, 5, 7, _COMP_PARAMS());
_test_check_annotation(tb, 0, 3, _COMP_PARAMS());
/* Remove annotation of "item" also removes the OBJ character */
{
int blen, len;
evas_textblock_cursor_pos_set(cur, 5);
blen = evas_textblock_cursor_paragraph_text_length_get(cur);
efl_text_annotation_del(tb, an);
len = evas_textblock_cursor_paragraph_text_length_get(cur);
ck_assert_int_eq(len, blen - 1);
_test_check_annotation(tb, 0, 5, _COMP_PARAMS());
}
/* Using annotations with new text API */
efl_text_set(tb, "hello");
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 5);
efl_text_annotation_insert(tb, start, end, "color=#fff");
_test_check_annotation(tb, 3, 3, _COMP_PARAMS("color=#fff"));
/* Old API */
evas_textblock_cursor_pos_set(cur, 5);
evas_textblock_cursor_text_prepend(cur, "a");
_test_check_annotation(tb, 0, 0, _COMP_PARAMS("color=#fff"));
_test_check_annotation(tb, 5, 5, _COMP_PARAMS());
/* Specific case with PS */
efl_text_set(tb, "hello\nworld");
evas_textblock_cursor_pos_set(start, 0);
evas_textblock_cursor_pos_set(end, 5);
efl_text_annotation_insert(tb, start, end, "color=#fff");
_test_check_annotation(tb, 4, 4, _COMP_PARAMS("color=#fff"));
evas_textblock_cursor_pos_set(cur, 4);
/* Cursor position is now: hello|\nworld */
evas_textblock_cursor_text_prepend(cur, "a");
_test_check_annotation(tb, 0, 0, _COMP_PARAMS("color=#fff"));
_test_check_annotation(tb, 5, 5, _COMP_PARAMS("color=#fff"));
/* Test getting of object item */
evas_textblock_cursor_pos_set(cur, 4);
an = efl_text_cursor_item_annotation_get(tb, cur);
ck_assert(!an);
an = efl_text_cursor_item_insert(tb, cur, "", "size=16x16");
evas_textblock_cursor_pos_set(cur, 4);
an = efl_text_cursor_item_annotation_get(tb, cur);
ck_assert(an);
ck_assert_str_eq("size=16x16 href=", efl_text_annotation_get(tb, an));
END_TB_TEST();
efl_text_cursor_position_set(start, 0);
efl_text_cursor_position_set(end, 3);
unsigned int count = efl_text_attribute_factory_attribute_clear(start, end);
fail_if(count != 3);
}
EFL_END_TEST;
@ -4543,7 +4364,7 @@ EFL_END_TEST;
fail_if(!efl_canvas_text_style_get(txt, NULL) || \
strcmp(style_buf, efl_canvas_text_style_get(txt, NULL))); \
cur_obj = efl_canvas_text_cursor_create(txt);\
cur = efl_text_cursor_handle_get(cur_obj); \
cur = evas_object_textblock_cursor_new(txt); \
fail_if(!cur); \
do \
{ \
@ -4554,6 +4375,7 @@ while (0)
do \
{ \
efl_del(cur_obj); \
evas_textblock_cursor_free(cur); \
efl_del(txt); \
evas_free(evas); \
} \