[Elm] Creating base smart class, to be extended

properly by real widgets.
I'm also creating a *compatibility* class on top of it, which extends
the old (unique) one to its old components, so that everything goes
unnoticed for the widgets.

Next, we'll be accessing class functions for widget hooks *on the base
class*, which will be proxied back to the instance ones.

Then, one by one the widgets will be translated to a proper
hierarchical smart class parentage, making extensibility and reuse
much better.

Last, but not least, since we'll be moving these hooks to the class,
where (almost) everything is a function, let's adapt to the future --
take away the "_func" suffix from them.

NB: there is ONE hook and associated data which was kept on the base,
for now: "show_region" stuff. I did that because scrollers need that
in order to work, right now. Keep in mind, though, the scrollers will
be reworked, so that fields ought to be changed soon, too.



SVN revision: 70704
This commit is contained in:
Gustavo Lima Chaves 2012-05-03 22:41:04 +00:00
parent a83d094b7c
commit 66f5d302ee
2 changed files with 946 additions and 292 deletions

File diff suppressed because it is too large Load Diff

View File

@ -188,6 +188,302 @@
#endif
#define ELM_INTERNAL_API_VERSION 7000
/**
* @defgroup Widget Widgets Extension Infrastructure
*
* This section is intended for people willing to create @b custom
* Elementary widgets or to contribute new (useful, unique) widgets
* upstream. If neither is your case, this text won't be of any use
* for you.
*
* Elementary widgets are built in a @b hierarchical fashion. The idea
* is to factorize as much code as possible between widgets with
* behavioral similarities, as long as to facilitate the creation of
* @b custom, new widgets, may the user need them.
*
* It all starts with a base class, which aggregates behaviour
* @b every Elementary widget is supposed to have:
* #Elm_Widget_Smart_Class. Every Elementary widget will be of that
* type, be it directly or by means of @b inheriting from it.
*
* #Elm_Widget_Smart_Class happens to be an @c Evas_Smart_Class. If
* you check out Evas' documentation on it, you'll see it's how one is
* supposed to create custom Evas objects, what Elementary widgets
* are.
*
* Once one instantiates an Elementary widget, since it inherits from
* #Elm_Widget_Smart_Class, the system will raise a class instance of
* that type for you. But that happens only @b once: the first time
* you ask for an Elementary widget (of a given type). All subsequent
* ones will only point to the very same class instance. Since it's
* the class which points to the functions implementing the behavior
* of objects of that type, all of the live instances of Elementary
* widgets (of that type) will share the same blob of code loaded in
* memory to execute their routines.
*
* Now go and take a look at #Elm_Widget_Smart_Class's fields. Because
* it inherits from Evas' base smart class, we got a field of that
* type as the first member, so that Evas can handle Elementary
* objects internally as if they were 'normal' Evas objects. Evas has
* the Evas-only behavior function pointers in there, so it's all it
* needs.
*
* Then, comes a version field, so that whenever we got to update or
* change the fields on our base smart class, there'll be a runtime
* check of the version expected by Elementary and the one provided by
* any code linking with it. A mismatch will show the developer of
* that code he/she needs to recompile and link its code to a newer
* version of Elementary.
*
* The next fields are the class functions itself. We call them
* 'virtual' because, as in object-oriented languages, one is supposed
* here to override them on inheriting classes. On most of
* inheritances you'll probably want to call the parent's version of
* the class function too: you must analise each case to tell.
*
* Take a look at #Elm_Widget_Smart_Data. That's private data bound to
* each Elementary object @b instance. It aggregates data needed for
* all widgets, since it's meant for the #Elm_Widget_Smart_Class-typed
* ones.
*
* When inheriting from that base type, instance data for this new
* class has to have, as the first member, a field of type
* #Elm_Widget_Smart_Data. This has to be respected recursively -- if
* a third class is to be created inheriting from the one that is a
* direct 'child' of #Elm_Widget_Smart_Class, then the private data on
* this third class has to have, as its first field, a variable of the
* type of the private data of the second class (its parent), direct
* child of #Elm_Widget_Smart_Class.
*
* [image here later, explaining process]
*
* It is from the base private data, #Elm_Widget_Smart_Data, that we
* reach an object's class functions, by the given object
* instance. This is the reason of the first field of that struct: a
* pointer set to point to its class when the object is instantiated.
*
* @section elm-migration Elementary's Migration to a hierarchical schema
*
* What's been stated before is a work in progress. Elementary 1.0 is
* @b not hierarchical in this way, but the idea is to get at this
* shape, now. This section is here to explain the process of
* migration, and it will be taken off once it's completed.
*
* We want to migrate widgets to the new schema progressively, one by
* one. In order for this to happen without hurting anyone during the
* process, it was made a @b compatibility class for Elementary
* widgets, to take place of the old, unique smart class for
* them. This is the role of #Elm_Widget_Compat_Smart_Class.
*
* All functions we had as 'hooks' before will be migrated to class
* functions. As you can see, all calls to @b instance hooks on the
* common code for widgets were replaced to <b> class function calls
* </b>, now. It just happens that, for
* #Elm_Widget_Compat_Smart_Class-typed widgets, i.e., the ones not
* migrated to the new schema yet, class calls are proxyed back to
* their instance 'hook' calls, that live on
* #Elm_Widget_Compat_Smart_Data structs. Those structs are
* #Elm_Widget_Smart_Data augmented with what is needed to reach the
* original widget's data field set, so that things go on @b unnoticed
* for the widgets awaiting translation to the new hierarchy.
*
* The following figure illustrates the old an new widget schemas,
* with highlights on their differences.
*
* @image html elm-widget-hierarchy.png
* @image rtf elm-widget-hierarchy.png
* @image latex elm-widget-hierarchy.eps
*/
/**
* @addtogroup Widget
* @{
*/
/**
* @def ELM_WIDGET_CLASS
*
* Use this macro to cast whichever subclass of
* #Elm_Widget_Smart_Class into it, so to acess its fields.
*
* @ingroup Widget
*/
#define ELM_WIDGET_CLASS(x) ((Elm_Widget_Smart_Class *) x)
/**
* @def ELM_WIDGET_DATA
*
* Use this macro to cast whichever subdata of
* #Elm_Widget_Smart_Data into it, so to acess its fields.
*
* @ingroup Widget
*/
#define ELM_WIDGET_DATA(x) ((Elm_Widget_Smart_Data *) x)
/**
* @def ELM_WIDGET_SMART_CLASS_VERSION
*
* Current version for Elementary widget @b base smart class, a value
* which goes to _Elm_Widget_Smart_Class::version.
*
* @ingroup Wiget
*/
#define ELM_WIDGET_SMART_CLASS_VERSION 1
/**
* @def ELM_WIDGET_SMART_CLASS_INIT
*
* Initializer for a whole #Elm_Widget_Smart_Class structure, with
* @c NULL values on its specific fields.
*
* @param smart_class_init initializer to use for the "base" field
* (#Evas_Smart_Class).
*
* @see EVAS_SMART_CLASS_INIT_NULL
* @see EVAS_SMART_CLASS_INIT_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION
* @see ELM_WIDGET_SMART_CLASS_INIT_NULL
* @see ELM_WIDGET_SMART_CLASS_INIT_NAME_VERSION
*
* @ingroup Widget
*/
#define ELM_WIDGET_SMART_CLASS_INIT(smart_class_init) \
{smart_class_init, ELM_WIDGET_SMART_CLASS_VERSION, NULL, NULL, NULL, NULL, \
NULL, NULL, NULL, NULL, NULL}
/**
* @def ELM_WIDGET_SMART_CLASS_INIT_NULL
*
* Initializer to zero out a whole #Elm_Widget_Smart_Class structure.
*
* @see ELM_WIDGET_SMART_CLASS_INIT_NAME_VERSION
* @see ELM_WIDGET_SMART_CLASS_INIT
*
* @ingroup Widget
*/
#define ELM_WIDGET_SMART_CLASS_INIT_NULL \
ELM_WIDGET_SMART_CLASS_INIT(EVAS_SMART_CLASS_INIT_NULL)
/**
* @def ELM_WIDGET_SMART_CLASS_INIT_NAME_VERSION
*
* Initializer to zero out a whole #Elm_Widget_Smart_Class structure and
* set its name and version.
*
* This is similar to #ELM_WIDGET_SMART_CLASS_INIT_NULL, but it will
* also set the version field of #Elm_Widget_Smart_Class (base field)
* to the latest #ELM_WIDGET_SMART_CLASS_VERSION and name it to the
* specific value.
*
* It will keep a reference to the name field as a <c>"const char *"</c>,
* i.e., the name must be available while the structure is
* used (hint: static or global variable!) and must not be modified.
*
* @see ELM_WIDGET_SMART_CLASS_INIT_NULL
* @see ELM_WIDGET_SMART_CLASS_INIT
*
* @ingroup Widget
*/
#define ELM_WIDGET_SMART_CLASS_INIT_NAME_VERSION(name) \
ELM_WIDGET_SMART_CLASS_INIT(EVAS_SMART_CLASS_INIT_NAME_VERSION(name))
/**
* Base widget smart class. It has the 'virtual' functions for all
* general, common actions on Elementary widgets.
*/
typedef struct _Elm_Widget_Smart_Class
{
Evas_Smart_Class base; /**< Base smart class struct, needed for all smart objects */
int version; /**< Version of this smart class definition */
Eina_Bool (*on_focus)(Evas_Object *obj); /**< 'Virtual' function handling receipt of focus on the widget */
Eina_Bool (*disable)(Evas_Object *obj); /**< 'Virtual' function on the widget being disabled */
Eina_Bool (*theme)(Evas_Object *obj); /**< 'Virtual' function on the widget being re-themed */
Eina_Bool (*translate)(Evas_Object *obj); /**< 'Virtual' function handling language changes on Elementary */
Eina_Bool (*event)(Evas_Object *obj,
Evas_Object *source,
Evas_Callback_Type type,
void *event_info); /**< 'Virtual' function handling input events on the widget */
Eina_Bool (*focus_next)(const Evas_Object *obj,
Elm_Focus_Direction dir,
Evas_Object **next); /**< 'Virtual' function handling passing focus to sub-objects */
Eina_Bool (*focus_direction)(const Evas_Object *obj,
const Evas_Object *base,
double degree,
Evas_Object **target,
double *weight); /**< 'Virtual' function handling passing focus to sub-objects <b>given a direction, in degrees</b> */
Eina_Bool (*sub_object_add)(Evas_Object *obj,
Evas_Object *sobj); /**< 'Virtual' function handling sub objects being added */
Eina_Bool (*sub_object_del)(Evas_Object *obj,
Evas_Object *sobj); /**< 'Virtual' function handling sub objects being removed */
} Elm_Widget_Smart_Class;
/**
* Base widget smart data. This is data bound to an Elementary object
* @b instance, so its particular to that specific object and not
* shared between all objects in its class. It is here, though, that
* we got a pointer to the object's class, the first field -- @c
* 'api'.
*/
typedef struct _Elm_Widget_Smart_Data
{
const Elm_Widget_Smart_Class *api; /**< This is the pointer to the object's class, from where we can reach/call its class functions */
Evas_Object *obj;
Evas_Object *parent_obj;
Evas_Object *parent2;
Evas_Coord x, y, w, h;
Eina_List *subobjs;
Evas_Object *resize_obj;
Evas_Object *hover_obj;
Eina_List *tooltips, *cursors;
Evas_Coord rx, ry, rw, rh;
int scroll_hold;
int scroll_freeze;
double scale;
Elm_Theme *theme;
const char *style;
const char *access_info;
unsigned int focus_order;
Eina_Bool focus_order_on_calc;
int child_drag_x_locked;
int child_drag_y_locked;
Eina_List *translate_strings;
Eina_List *focus_chain;
Eina_List *event_cb;
/* subject to later analysis: to be changed by something different */
void *on_show_region_data;
void (*on_show_region)(void *data,
Evas_Object *obj);
Eina_Bool drag_x_locked : 1;
Eina_Bool drag_y_locked : 1;
Eina_Bool can_focus : 1;
Eina_Bool child_can_focus : 1;
Eina_Bool focused : 1;
Eina_Bool top_win_focused : 1;
Eina_Bool tree_unfocusable : 1;
Eina_Bool highlight_ignore : 1;
Eina_Bool highlight_in_theme : 1;
Eina_Bool disabled : 1;
Eina_Bool is_mirrored : 1;
Eina_Bool mirrored_auto_mode : 1; /* This is
* TRUE by
* default */
Eina_Bool still_in : 1;
} Elm_Widget_Smart_Data;
/**
* @}
*/
typedef struct _Elm_Tooltip Elm_Tooltip;
typedef struct _Elm_Cursor Elm_Cursor;
@ -327,8 +623,8 @@ EAPI void elm_widget_content_unset_hook_set(Evas_Object *obj, Elm_Wi
EAPI void elm_widget_on_focus_region_hook_set(Evas_Object *obj, void (*func)(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h));
EAPI void elm_widget_data_set(Evas_Object *obj, void *data);
EAPI void *elm_widget_data_get(const Evas_Object *obj);
EAPI void elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj);
EAPI void elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj);
EAPI Eina_Bool elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj);
EAPI Eina_Bool elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj);
EAPI const Eina_List *elm_widget_sub_object_list_get(const Evas_Object *obj);
EAPI void elm_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj);
EAPI void elm_widget_hover_object_set(Evas_Object *obj, Evas_Object *sobj);
@ -370,6 +666,7 @@ EAPI Evas_Object *elm_widget_parent_get(const Evas_Object *obj);
EAPI Evas_Object *elm_widget_parent2_get(const Evas_Object *obj);
EAPI void elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent);
EAPI void elm_widget_focus_steal(Evas_Object *obj);
EAPI const Elm_Widget_Smart_Class *elm_widget_smart_class_get(void);
/**
* @internal