Efl: Add Efl.Part and switch to it

This should now fix the part API usage once and for all.
EFL should have no part name in any of its APIs beyond
the Efl.Part interface.

Part proxy objects (may be real objects) have a lifetime
of only one function call, in a fashion similar to eo_super.

@feature
This commit is contained in:
Jean-Philippe ANDRE 2016-05-19 03:20:09 +09:00 committed by Jean-Philippe Andre
parent 93ab200d67
commit d0f141077e
9 changed files with 90 additions and 47 deletions

View File

@ -10,6 +10,7 @@ efl_eolian_files = \
lib/efl/interfaces/efl_control.eo \
lib/efl/interfaces/efl_file.eo \
lib/efl/interfaces/efl_image_load.eo \
lib/efl/interfaces/efl_part.eo \
lib/efl/interfaces/efl_player.eo \
lib/efl/interfaces/efl_text.eo \
lib/efl/interfaces/efl_text_properties.eo \

View File

@ -21,6 +21,7 @@ struct _Edje_Part_Data
Edje *ed;
Edje_Real_Part *rp;
const char *part;
Eina_Bool temp;
};
struct _Part_Item_Iterator
@ -31,26 +32,12 @@ struct _Part_Item_Iterator
Eo *object;
};
static Eina_Bool
_del_cb(void *data, const Eo_Event *event EINA_UNUSED)
{
Edje_Real_Part *rp = data;
rp->typedata.container->eo_proxy = NULL;
return EO_CALLBACK_CONTINUE;
}
Eo *
_edje_box_internal_proxy_get(Edje_Object *obj, Edje *ed, Edje_Real_Part *rp)
{
Efl_Canvas_Layout_Internal_Box *eo = rp->typedata.container->eo_proxy;
if (eo) return eo;
eo = eo_add(BOX_CLASS, obj, efl_canvas_layout_internal_box_real_part_set(eo_self, ed, rp, rp->part->name));
eo_event_callback_add(eo, EO_EVENT_DEL, _del_cb, rp);
rp->typedata.container->eo_proxy = eo;
return eo;
// TODO: optimize (cache)
return eo_add(BOX_CLASS, obj,
efl_canvas_layout_internal_box_real_part_set(eo_self, ed, rp, rp->part->name));
}
EOLIAN static void
@ -59,6 +46,7 @@ _efl_canvas_layout_internal_box_real_part_set(Eo *obj EINA_UNUSED, Edje_Box_Data
pd->ed = ed;
pd->rp = rp;
pd->part = part;
pd->temp = EINA_TRUE;
}
EOLIAN static Eo_Base *
@ -261,15 +249,9 @@ _efl_canvas_layout_internal_box_efl_pack_linear_pack_direction_get(Eo *obj EINA_
Eo *
_edje_table_internal_proxy_get(Edje_Object *obj, Edje *ed, Edje_Real_Part *rp)
{
Efl_Canvas_Layout_Internal_Box *eo = rp->typedata.container->eo_proxy;
if (eo) return eo;
eo = eo_add(TABLE_CLASS, obj, efl_canvas_layout_internal_table_real_part_set(eo_self, ed, rp, rp->part->name));
eo_event_callback_add(eo, EO_EVENT_DEL, _del_cb, rp);
rp->typedata.container->eo_proxy = eo;
return eo;
// TODO: optimize (cache)
return eo_add(TABLE_CLASS, obj,
efl_canvas_layout_internal_table_real_part_set(eo_self, ed, rp, rp->part->name));
}
EOLIAN static void
@ -278,6 +260,7 @@ _efl_canvas_layout_internal_table_real_part_set(Eo *obj EINA_UNUSED, Edje_Table_
pd->ed = ed;
pd->rp = rp;
pd->part = part;
pd->temp = EINA_TRUE;
}
EOLIAN static Eo_Base *
@ -453,7 +436,7 @@ _efl_canvas_layout_internal_table_efl_pack_grid_grid_position_get(Eo *obj EINA_U
#ifdef DEGUG
#define PART_BOX_GET(obj, part, ...) ({ \
Eo *__box = efl_content_get(obj, part); \
Eo *__box = efl_part(obj, part); \
if (!__box || !eo_isa(__box, EFL_CANVAS_LAYOUT_INTERNAL_BOX_CLASS)) \
{ \
ERR("No such box part '%s' in layout %p", part, obj); \
@ -462,7 +445,7 @@ _efl_canvas_layout_internal_table_efl_pack_grid_grid_position_get(Eo *obj EINA_U
__box; })
#else
#define PART_BOX_GET(obj, part, ...) ({ \
Eo *__box = efl_content_get(obj, part); \
Eo *__box = efl_part(obj, part); \
if (!__box) return __VA_ARGS__; \
__box; })
#endif
@ -531,7 +514,7 @@ edje_object_part_box_remove_all(Edje_Object *obj, const char *part, Eina_Bool cl
#ifdef DEBUG
#define PART_TABLE_GET(obj, part, ...) ({ \
Eo *__table = efl_content_get(obj, part); \
Eo *__table = efl_part(obj, part); \
if (!__table || !eo_isa(__table, EFL_CANVAS_LAYOUT_INTERNAL_TABLE_CLASS)) \
{ \
ERR("No such table part '%s' in layout %p", part, obj); \
@ -540,7 +523,7 @@ edje_object_part_box_remove_all(Edje_Object *obj, const char *part, Eina_Bool cl
__table; })
#else
#define PART_TABLE_GET(obj, part, ...) ({ \
Eo *__table = efl_content_get(obj, part); \
Eo *__table = efl_part(obj, part); \
if (!__table) return __VA_ARGS__; \
__table; })
#endif

View File

@ -1596,7 +1596,6 @@ _edje_file_del(Edje *ed)
_edje_box_layout_free_data(rp->typedata.container->anim);
rp->typedata.container->anim = NULL;
}
eo_unref(rp->typedata.container->eo_proxy);
free(rp->typedata.container);
}
else if ((rp->type == EDJE_RP_TYPE_TEXT) &&

View File

@ -1,6 +1,6 @@
import edje_types;
class Edje.Object (Evas.Smart.Clipped, Efl.File, Efl.Container)
class Edje.Object (Evas.Smart.Clipped, Efl.File, Efl.Container, Efl.Part)
{
legacy_prefix: edje_object;
eo_prefix: edje_obj;
@ -2005,6 +2005,7 @@ class Edje.Object (Evas.Smart.Clipped, Efl.File, Efl.Container)
Efl.Container.content_unset;
Efl.Container.content_remove;
Efl.Container.content_part_name.get;
Efl.Part.part;
}
events {
recalc; [[Edje re-calculated the object.]]

View File

@ -1897,7 +1897,6 @@ struct _Edje_Real_Part_Container
{
Eina_List *items; // 4 //FIXME: only if table/box
Edje_Part_Box_Animation *anim; // 4 //FIXME: Used only if box
Eo *eo_proxy;
};
struct _Edje_Real_Part_Swallow

View File

@ -3897,23 +3897,15 @@ _edje_object_efl_container_content_get(Eo *obj, Edje *ed, const char *part)
rp = _edje_real_part_recursive_get(&ed, part);
if (!rp) return NULL;
switch (rp->type)
if (rp->type != EDJE_RP_TYPE_SWALLOW)
{
case EDJE_RP_TYPE_SWALLOW:
if (!rp->typedata.swallow) return NULL;
return rp->typedata.swallow->swallowed_object;
case EDJE_RP_TYPE_CONTAINER:
if (rp->part->type == EDJE_PART_TYPE_BOX)
return _edje_box_internal_proxy_get(obj, ed, rp);
else if (rp->part->type == EDJE_PART_TYPE_TABLE)
return _edje_table_internal_proxy_get(obj, ed, rp);
else return NULL;
case EDJE_RP_TYPE_TEXT:
WRN("not implemented yet");
return NULL;
default:
ERR("Edje group '%s' part '%s' is not a swallow. Did "
"you mean to call efl_part() instead?", ed->group, part);
return NULL;
}
if (!rp->typedata.swallow) return NULL;
return rp->typedata.swallow->swallowed_object;
}
/* new in eo */
@ -3943,6 +3935,26 @@ _edje_object_efl_container_content_part_name_get(Eo *obj EINA_UNUSED, Edje *ed E
return rp->part->name;
}
EOLIAN Eo *
_edje_object_efl_part_part(Eo *obj, Edje *ed, const char *part)
{
Edje_Real_Part *rp;
if ((!ed) || (!part)) return NULL;
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(&ed, part);
if (!rp) return NULL;
if (rp->part->type == EDJE_PART_TYPE_BOX)
return _edje_box_internal_proxy_get(obj, ed, rp);
else if (rp->part->type == EDJE_PART_TYPE_TABLE)
return _edje_table_internal_proxy_get(obj, ed, rp);
else return NULL; /* FIXME/TODO: text & others (color, ...) */
}
EOLIAN void
_edje_object_size_min_get(Eo *obj EINA_UNUSED, Edje *ed, Evas_Coord *minw, Evas_Coord *minh)
{

View File

@ -71,6 +71,7 @@ typedef Efl_Gfx_Path_Command_Type Efl_Gfx_Path_Command;
#include "interfaces/efl_image.eo.h"
#include "interfaces/efl_image_animated.eo.h"
#include "interfaces/efl_image_load.eo.h"
#include "interfaces/efl_part.eo.h"
#include "interfaces/efl_player.eo.h"
#include "interfaces/efl_text.eo.h"
#include "interfaces/efl_text_properties.eo.h"

View File

@ -9,6 +9,7 @@
#include "interfaces/efl_image.eo.c"
#include "interfaces/efl_image_animated.eo.c"
#include "interfaces/efl_image_load.eo.c"
#include "interfaces/efl_part.eo.c"
#include "interfaces/efl_player.eo.c"
#include "interfaces/efl_text.eo.c"
#include "interfaces/efl_text_properties.eo.c"

View File

@ -0,0 +1,46 @@
import eo_base;
interface Efl.Part
{
[[Interface for objects supporting named parts.
An object implementing this interface will be able to
provide access to some of its sub-objects by name.
This gives access to parts as defined in a widget's
theme.
Part proxy objects have a special lifetime that
is limited to one and only one function call.
In other words, the caller does not hold a reference
to this proxy object. It may be possible, in languages
that allow it, to get an extra reference to this part
object and extend its lifetime to more than a single
function call.
In pseudo-code, this means only the following two
use cases are supported:
obj.func(part(obj, "part"), args)
And:
part = ref(part(obj, "part"))
func1(part, args)
func2(part, args)
func3(part, args)
unref(part)
]]
methods {
part @const {
[[Get a proxy object referring to a part of an object.
The returned object is valid for only a single function call.
]]
params {
name: const(char)*; [[The part name.]]
}
return: Eo.Base; [[A (proxy) object, valid for a single call.]]
}
}
}