Edje: Added mirrored mode. Mirrored mode is used for UI-mirroring. It lets you mirror edje objects automatically (it also sends signals to the .edc code so you can do tweaks if you want), no need to create a special theme just for rtl layouts.

This is controlled by the two added API functions.
The changes in Elementary that utilize these functions will be committed soon.

SVN revision: 56635
This commit is contained in:
Tom Hacohen 2011-02-01 13:26:49 +00:00
parent 6e7b0dffd7
commit 5e33a75553
10 changed files with 334 additions and 42 deletions

View File

@ -12,3 +12,5 @@ Jihoon Kim <jihoon48.kim@samsung.com>
Tiago Falcão <tiago@profusion.mobi>
Davide Andreoli <dave@gurumeditation.it>
Sebastian Dransfeld <sd@tango.flipp.net>
Tom Hacohen <tom@stosb.com>
Aharon Hillel <a.hillel@partner.samsung.com>

View File

@ -102,6 +102,7 @@ static void st_collections_group_alias(void);
static void st_collections_group_min(void);
static void st_collections_group_max(void);
static void st_collections_group_data_item(void);
static void st_collections_group_orientation(void);
static void ob_collections_group_script(void);
static void ob_collections_group_lua_script(void);
@ -290,6 +291,7 @@ New_Statement_Handler statement_handlers[] =
{"collections.group.alias", st_collections_group_alias},
{"collections.group.min", st_collections_group_min},
{"collections.group.max", st_collections_group_max},
{"collections.group.orientation", st_collections_group_orientation},
{"collections.group.data.item", st_collections_group_data_item},
{"collections.group.externals.external", st_externals_external}, /* dup */
{"collections.group.image", st_images_image}, /* dup */
@ -1998,6 +2000,35 @@ st_collections_group_data_item(void)
eina_hash_direct_add(pc->data, key, es);
}
/**
@page edcref
@property
orientation
@parameters
enum AUTO, LTR, RTL
@effect
This defines GROUP orientation.
This is useful if you want match interface orientation with language.
AUTO - Follow system defs.
LTR - suitable for Left To Right Languages (latin)
RTL - suitable for Right To Left Languages (Hebrew, Arabic interface)
@endproperty
*/
static void
st_collections_group_orientation(void)
{
Edje_Part_Collection *pc;
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
pc->prop.orientation = parse_enum(0,
"AUTO", EDJE_ORIENTATION_AUTO,
"LTR", EDJE_ORIENTATION_LTR,
"RTL", EDJE_ORIENTATION_RTL,
NULL);
}
/**
@page edcref
@block

View File

@ -502,6 +502,8 @@ typedef Evas_Object *(*Edje_Item_Provider_Cb) (void *data, Evas_Object *obj, c
EAPI double edje_scale_get (void);
EAPI Eina_Bool edje_object_scale_set (Evas_Object *obj, double scale);
EAPI double edje_object_scale_get (const Evas_Object *obj);
EAPI void edje_object_mirrored_set (Evas_Object *obj, Eina_Bool rtl);
EAPI Eina_Bool edje_object_mirrored_get (const Evas_Object *obj);
/* edje_load.c */
EAPI Eina_List *edje_file_collection_list (const char *file);

View File

@ -46,21 +46,26 @@ _edje_file_coll_open(Edje_File *edf, const char *coll)
id = ce->id;
if (id < 0) return NULL;
#define INIT_EMP(Tp, Sz, Ce) \
buffer = alloca(strlen(ce->entry) + strlen(#Tp) + 2); \
sprintf(buffer, "%s/%s", ce->entry, #Tp); \
#define INIT_EMP(Tp, Sz, Ce) \
buffer = alloca(strlen(ce->entry) + strlen(#Tp) + 2); \
sprintf(buffer, "%s/%s", ce->entry, #Tp); \
Ce->mp.Tp = eina_mempool_add("one_big", buffer, NULL, sizeof (Sz), Ce->count.Tp); \
_emp_##Tp = Ce->mp.Tp;
INIT_EMP(RECTANGLE, Edje_Part_Description_Common, ce);
INIT_EMP(TEXT, Edje_Part_Description_Text, ce);
INIT_EMP(IMAGE, Edje_Part_Description_Image, ce);
INIT_EMP(SWALLOW, Edje_Part_Description_Common, ce);
INIT_EMP(TEXTBLOCK, Edje_Part_Description_Text, ce);
INIT_EMP(GROUP, Edje_Part_Description_Common, ce);
INIT_EMP(BOX, Edje_Part_Description_Box, ce);
INIT_EMP(TABLE, Edje_Part_Description_Table, ce);
INIT_EMP(EXTERNAL, Edje_Part_Description_External, ce);
#define INIT_EMP_BOTH(Tp, Sz, Ce) \
INIT_EMP(Tp, Sz, Ce) \
Ce->mp_rtl.Tp = eina_mempool_add("one_big", buffer, NULL, \
sizeof (Sz), Ce->count.Tp);
INIT_EMP_BOTH(RECTANGLE, Edje_Part_Description_Common, ce);
INIT_EMP_BOTH(TEXT, Edje_Part_Description_Text, ce);
INIT_EMP_BOTH(IMAGE, Edje_Part_Description_Image, ce);
INIT_EMP_BOTH(SWALLOW, Edje_Part_Description_Common, ce);
INIT_EMP_BOTH(TEXTBLOCK, Edje_Part_Description_Text, ce);
INIT_EMP_BOTH(GROUP, Edje_Part_Description_Common, ce);
INIT_EMP_BOTH(BOX, Edje_Part_Description_Box, ce);
INIT_EMP_BOTH(TABLE, Edje_Part_Description_Table, ce);
INIT_EMP_BOTH(EXTERNAL, Edje_Part_Description_External, ce);
INIT_EMP(part, Edje_Part, ce);
snprintf(buf, sizeof(buf), "edje/collections/%i", id);

View File

@ -5,6 +5,9 @@
#define FLAG_Y 0x02
#define FLAG_XY (FLAG_X | FLAG_Y)
static void _edje_part_make_rtl(Edje_Part_Description_Common *desc);
static Edje_Part_Description_Common *_edje_get_description_by_orientation(Edje *ed, Edje_Part_Description_Common *src, Edje_Part_Description_Common **dst, unsigned char type);
static void _edje_part_recalc_single(Edje *ed, Edje_Real_Part *ep,
Edje_Part_Description_Common *desc, Edje_Part_Description_Common *chosen_desc,
Edje_Real_Part *rel1_to_x, Edje_Real_Part *rel1_to_y,
@ -60,31 +63,172 @@ _edje_part_pos_set(Edje *ed, Edje_Real_Part *ep, int mode, FLOAT_T pos)
#endif
}
/**
* Returns part description
*
* @internal
*
* Converts part description to RTL-desc.
*
* @param desc Pointer to desc buffer.
*
**/
static void
_edje_part_make_rtl(Edje_Part_Description_Common *desc)
{
double t;
int i;
if(!desc)
return;
/* This makes alignment right-oriented */
desc->align.x = 1.0 - desc->align.x;
/* same as above for relative components */
t = desc->rel1.relative_x;
desc->rel1.relative_x = 1.0 - desc->rel2.relative_x;
desc->rel2.relative_x = 1.0 - t;
/* +1 and +1 are because how edje works with right
* side borders - nothing is printed beyond that limit
*
* rel2 is now to the left of rel1, and Edje assumes
* the opposite so we switch corners on x-axis to define
* offset from right to left */
i = desc->rel1.offset_x;
desc->rel1.offset_x = -(desc->rel2.offset_x + 1);
desc->rel2.offset_x = -(i + 1);
i = desc->rel1.id_x;
desc->rel1.id_x = desc->rel2.id_x;
desc->rel2.id_x = i;
}
/**
* Returns part description
*
* @internal
*
* Returns part description according to object orientation.
* When object is in RTL-orientation (RTL flag is set)
* this returns the RTL-desc of it.
* RTL-desc would be allocated if was not created by a previous call.
* The dst pointer is updated in case of an allocation.
*
* @param ed Edje object.
* @param src The Left To Right (LTR), original desc.
* @param dst Pointer to Right To Left (RTL) desc-list.
* @param type name of dec type. Example: "default".
*
* @return Edje part description.
*
**/
static Edje_Part_Description_Common *
_edje_get_description_by_orientation(Edje *ed, Edje_Part_Description_Common *src, Edje_Part_Description_Common **dst, unsigned char type)
{
Edje_Part_Description_Common *desc_rtl = NULL;
Edje_Part_Collection_Directory_Entry *ce;
size_t memsize = 0;
/* RTL flag is not set, return original description */
if(!edje_object_mirrored_get(ed->obj))
return src;
if(*dst)
return *dst; /* Was allocated before and we should use it */
#define EDIT_ALLOC_POOL_RTL(Short, Type, Name) \
case EDJE_PART_TYPE_##Short: \
{ \
Edje_Part_Description_##Type *Name; \
Name = eina_mempool_malloc(ce->mp_rtl.Short, \
sizeof (Edje_Part_Description_##Type)); \
memset(Name, 0, sizeof(Edje_Part_Description_##Type)); \
desc_rtl = &Name->common; \
memsize = sizeof(Edje_Part_Description_##Type); \
break; \
}
ce = eina_hash_find(ed->file->collection, ed->group);
switch (type)
{
case EDJE_PART_TYPE_RECTANGLE:
desc_rtl = eina_mempool_malloc(ce->mp_rtl.RECTANGLE,
sizeof (Edje_Part_Description_Common));
ce->count.RECTANGLE++;
memsize = sizeof(Edje_Part_Description_Common);
break;
case EDJE_PART_TYPE_SWALLOW:
desc_rtl = eina_mempool_malloc(ce->mp_rtl.SWALLOW,
sizeof (Edje_Part_Description_Common));
ce->count.SWALLOW++;
memsize = sizeof(Edje_Part_Description_Common);
break;
case EDJE_PART_TYPE_GROUP:
desc_rtl = eina_mempool_malloc(ce->mp_rtl.GROUP,
sizeof (Edje_Part_Description_Common));
ce->count.GROUP++;
memsize = sizeof(Edje_Part_Description_Common);
break;
EDIT_ALLOC_POOL_RTL(TEXT, Text, text);
EDIT_ALLOC_POOL_RTL(TEXTBLOCK, Text, text);
EDIT_ALLOC_POOL_RTL(IMAGE, Image, image);
EDIT_ALLOC_POOL_RTL(BOX, Box, box);
EDIT_ALLOC_POOL_RTL(TABLE, Table, table);
EDIT_ALLOC_POOL_RTL(EXTERNAL, External, external_params);
}
if(desc_rtl)
memcpy(desc_rtl, src, memsize);
_edje_part_make_rtl(desc_rtl);
*dst = desc_rtl;
return desc_rtl;
}
Edje_Part_Description_Common *
_edje_part_description_find(Edje *ed __UNUSED__, Edje_Real_Part *rp, const char *name,
_edje_part_description_find(Edje *ed, Edje_Real_Part *rp, const char *name,
double val)
{
Edje_Part *ep = rp->part;
Edje_Part_Description_Common *ret = NULL;
Edje_Part_Description_Common *d;
double min_dst = 99999.0;
unsigned int i;
/* RTL flag is set, return RTL description */
if(edje_object_mirrored_get(ed->obj))
if(!ep->other.desc_rtl)
ep->other.desc_rtl = (Edje_Part_Description_Common **)
calloc(ep->other.desc_count,
sizeof (Edje_Part_Description_Common *));
if (!strcmp(name, "default") && val == 0.0)
return ep->default_desc;
return _edje_get_description_by_orientation(ed,
ep->default_desc, &ep->default_desc_rtl, ep->type);
if (!strcmp(name, "custom"))
return rp->custom ? rp->custom->description : NULL;
return rp->custom ?
_edje_get_description_by_orientation(ed, rp->custom->description,
&rp->custom->description_rtl, ep->type) : NULL;
if (!strcmp(name, "default"))
{
ret = ep->default_desc;
ret = _edje_get_description_by_orientation(ed, ep->default_desc,
&ep->default_desc_rtl, ep->type);
min_dst = ABS(ep->default_desc->state.value - val);
}
for (i = 0; i < ep->other.desc_count; ++i)
{
d = ep->other.desc[i];
if (d->state.name && !strcmp(d->state.name, name))
{
double dst;
@ -92,7 +236,8 @@ _edje_part_description_find(Edje *ed __UNUSED__, Edje_Real_Part *rp, const char
dst = ABS(d->state.value - val);
if (dst < min_dst)
{
ret = d;
ret = _edje_get_description_by_orientation(ed, d,
&ep->other.desc_rtl[i], ep->type);
min_dst = dst;
}
}
@ -265,7 +410,7 @@ _edje_recalc_do(Edje *ed)
ep = ed->table_parts[i];
if (ep->calculated != FLAG_XY)
_edje_part_recalc(ed, ep, (~ep->calculated) & FLAG_XY);
_edje_part_recalc(ed, ep, (~ep->calculated) & FLAG_XY);
}
if (!ed->calc_only) ed->recalc = 0;
#ifdef EDJE_CALC_CACHE

View File

@ -785,4 +785,5 @@ _edje_edd_init(void)
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "part", part, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "script_only", script_only, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "lua_script_only", lua_script_only, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "prop.orientation", prop.orientation, EET_T_INT);
}

View File

@ -25,12 +25,15 @@ static Eina_List *_edje_swallows_collect(Edje *ed);
EAPI Eina_Bool
edje_object_file_set(Evas_Object *obj, const char *file, const char *group)
{
Eina_Bool ret;
Edje *ed;
ed = _edje_fetch(obj);
if (!ed)
return EINA_FALSE;
return ed->api->file_set(obj, file, group);
ret = ed->api->file_set(obj, file, group);
_edje_object_orientation_inform(obj);
return ret;
}
/* FIXDOC: Verify/expand doc. */
@ -373,6 +376,10 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
if (ed->collection)
{
if (ed->collection->prop.orientation != EDJE_ORIENTATION_AUTO)
ed->is_rtl = (ed->collection->prop.orientation ==
EDJE_ORIENTATION_RTL);
if (ed->collection->script_only)
{
ed->load_error = EDJE_LOAD_ERROR_NONE;
@ -446,7 +453,8 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
_edje_ref(rp->edje);
rp->part = ep;
parts = eina_list_append(parts, rp);
rp->param1.description = ep->default_desc;
rp->param1.description = _edje_part_description_find(ed,
rp, "default", 0.0);
rp->chosen_description = rp->param1.description;
if (!rp->param1.description)
ERR("no default part description!");
@ -1204,6 +1212,10 @@ _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec, Edje_Part_Collec
_edje_collection_free_part_description_clean(ep->type, ep->other.desc[j], edf->free_strings);
free(ep->other.desc);
/* Alloc for RTL objects in edje_calc.c:_edje_part_description_find() */
if(ep->other.desc_rtl)
free(ep->other.desc_rtl);
free(ep->items);
// technically need this - but we ASSUME we use "one_big" so everything gets
// freed in one go lower down when we del the mempool... but what if pool goes
@ -1251,6 +1263,16 @@ _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec, Edje_Part_Collec
eina_mempool_del(ce->mp.part);
memset(&ce->mp, 0, sizeof (ce->mp));
eina_mempool_del(ce->mp_rtl.RECTANGLE);
eina_mempool_del(ce->mp_rtl.TEXT);
eina_mempool_del(ce->mp_rtl.IMAGE);
eina_mempool_del(ce->mp_rtl.SWALLOW);
eina_mempool_del(ce->mp_rtl.TEXTBLOCK);
eina_mempool_del(ce->mp_rtl.GROUP);
eina_mempool_del(ce->mp_rtl.BOX);
eina_mempool_del(ce->mp_rtl.TABLE);
eina_mempool_del(ce->mp_rtl.EXTERNAL);
memset(&ce->mp_rtl, 0, sizeof (ce->mp_rtl));
free(ec);
ce->ref = NULL;
}

View File

@ -365,6 +365,10 @@ typedef struct _Edje_Part_Box_Animation Edje_Part_Box_Animation;
#define EDJE_ENTRY_CURSOR_MODE_UNDER 0
#define EDJE_ENTRY_CURSOR_MODE_BEFORE 1
#define EDJE_ORIENTATION_AUTO 0
#define EDJE_ORIENTATION_LTR 1
#define EDJE_ORIENTATION_RTL 2
#define EDJE_PART_PATH_SEPARATOR ':'
#define EDJE_PART_PATH_SEPARATOR_STRING ":"
#define EDJE_PART_PATH_SEPARATOR_INDEXL '['
@ -543,6 +547,16 @@ struct _Edje_Program_After /* the action to run after another action */
};
/*----------*/
#define PART_TYPE_FIELDS(TYPE) \
TYPE RECTANGLE; \
TYPE TEXT; \
TYPE IMAGE; \
TYPE SWALLOW; \
TYPE TEXTBLOCK; \
TYPE GROUP; \
TYPE BOX; \
TYPE TABLE; \
TYPE EXTERNAL;
struct _Edje_Part_Collection_Directory_Entry
{
@ -551,32 +565,21 @@ struct _Edje_Part_Collection_Directory_Entry
struct
{
int RECTANGLE;
int TEXT;
int IMAGE;
int SWALLOW;
int TEXTBLOCK;
int GROUP;
int BOX;
int TABLE;
int EXTERNAL;
PART_TYPE_FIELDS(int)
int part;
} count;
struct
{
Eina_Mempool *RECTANGLE;
Eina_Mempool *TEXT;
Eina_Mempool *IMAGE;
Eina_Mempool *SWALLOW;
Eina_Mempool *TEXTBLOCK;
Eina_Mempool *GROUP;
Eina_Mempool *BOX;
Eina_Mempool *TABLE;
Eina_Mempool *EXTERNAL;
PART_TYPE_FIELDS(Eina_Mempool *)
Eina_Mempool *part;
} mp;
struct
{
PART_TYPE_FIELDS(Eina_Mempool *)
} mp_rtl; /* For Right To Left interface */
Edje_Part_Collection *ref;
};
@ -635,6 +638,7 @@ struct _Edje_Part_Collection
struct {
Edje_Size min, max;
unsigned char orientation;
} prop;
int references;
@ -683,6 +687,7 @@ typedef struct _Edje_Part_Description_List Edje_Part_Description_List;
struct _Edje_Part_Description_List
{
Edje_Part_Description_Common **desc;
Edje_Part_Description_Common **desc_rtl; /* desc for Right To Left interface */
unsigned int desc_count;
};
@ -690,6 +695,7 @@ struct _Edje_Part
{
const char *name; /* the name if any of the part */
Edje_Part_Description_Common *default_desc; /* the part descriptor for default */
Edje_Part_Description_Common *default_desc_rtl; /* default desc for Right To Left interface */
Edje_Part_Description_List other; /* other possible descriptors */
@ -986,6 +992,7 @@ struct _Edje
int load_error;
int freeze;
FLOAT_T scale;
Eina_Bool is_rtl : 1;
struct {
Edje_Text_Change_Cb func;
@ -1077,6 +1084,7 @@ struct _Edje_Real_Part_Set
struct _Edje_Real_Part_State
{
Edje_Part_Description_Common *description; // 4
Edje_Part_Description_Common *description_rtl; // 4
Edje_Real_Part *rel1_to_x; // 4
Edje_Real_Part *rel1_to_y; // 4
Edje_Real_Part *rel2_to_x; // 4
@ -1087,8 +1095,8 @@ struct _Edje_Real_Part_State
#endif
void *external_params; // 4
Edje_Real_Part_Set *set; // 4
}; // 28
// WITH EDJE_CALC_CACHE 128
}; // 32
// WITH EDJE_CALC_CACHE 132
struct _Edje_Real_Part_Drag
{
@ -1832,4 +1840,6 @@ void _edje_lua2_script_func_signal(Edje *ed, const char *sig, const char *src);
const char *edje_string_get(const Edje_String *es);
const char *edje_string_id_get(const Edje_String *es);
void _edje_object_orientation_inform(Evas_Object *obj);
#endif

View File

@ -30,12 +30,18 @@ Eina_List *_edje_edjes = NULL;
EAPI Evas_Object *
edje_object_add(Evas *evas)
{
Edje *ed;
Evas_Object *e;
if (!_edje_smart)
{
_edje_object_smart_set(&_edje_smart_class);
_edje_smart = evas_smart_class_new((Evas_Smart_Class *)&_edje_smart_class);
}
return evas_object_smart_add(evas, _edje_smart);
e = evas_object_smart_add(evas, _edje_smart);
ed = _edje_fetch(e);
return e;
}
void
@ -103,6 +109,7 @@ _edje_smart_add(Evas_Object *obj)
evas_object_move(ed->clipper, -10000, -10000);
evas_object_resize(ed->clipper, 20000, 20000);
evas_object_pass_events_set(ed->clipper, 1);
ed->is_rtl = EINA_FALSE;
ed->have_objects = 1;
ed->references = 1;

View File

@ -261,6 +261,73 @@ edje_object_scale_get(const Evas_Object *obj)
return TO_DOUBLE(ed->scale);
}
/**
* Get the RTL orientation for this object.
*
* You can RTL orientation explicitly with edje_object_mirrored_set.
*
* @param obj the smart object
* @return if flag is set or not.
*
**/
EAPI Eina_Bool
edje_object_mirrored_get(const Evas_Object *obj)
{
Edje *ed;
ed = _edje_fetch(obj);
if (!ed) return EINA_FALSE;
return ed->is_rtl;
}
void
_edje_object_orientation_inform(Evas_Object *obj)
{
if (edje_object_mirrored_get(obj))
edje_object_signal_emit(obj, "edje,state,rtl", "edje");
else
edje_object_signal_emit(obj, "edje,state,ltr", "edje");
}
/**
* Set the RTL orientation for this object.
*
* @param obj the smart object
* @rtl new value of flag EINA_TRUE/EINA_FALSE
*
**/
EAPI void
edje_object_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
{
Edje *ed;
int i;
ed = _edje_fetch(obj);
if (!ed) return;
if (ed->is_rtl == rtl) return;
ed->is_rtl = rtl;
for (i = 0 ; i < ed->table_parts_size ; i++)
{
Edje_Real_Part *ep;
const char *s;
double v;
ep = ed->table_parts[i];
s = ep->param1.description->state.name,
v = ep->param1.description->state.value;
_edje_part_description_apply(ed, ep, s, v , NULL, 0.0);
ep->chosen_description = ep->param1.description;
}
_edje_recalc_do(ed);
_edje_object_orientation_inform(obj);
return;
}
/**
* @brief Get Edje object data.
*