efl

Форк
0
/
eo_tutorial.dox 
315 строк · 13.5 Кб
1
/**
2
 * @page Eo_Tutorial Eo Tutorial
3
 *
4
 * @section Purpose
5
 * The purpose of this document is to explain how to work with Eo, how to port your code to Eo and what are the common pitfalls. It doesn't explain how it works inside.
6
 *
7
 * @section Description
8
 * Eo is an Object oriented infrastructure for the EFL. It is a API/ABI safe library.
9
 *
10
 * It supports inheritance, mixins, interfaces and composite objects.\n
11
 * Every class can implement functions from every other class.\n
12
 * It supports event signals, function overrides, private/protected/public/etc. variables and functions.
13
 *
14
 * At the creation of the class, a "virtual table" is filled with the needed functions.\n
15
 * The key of this table is a (class id, function id) tuple.
16
 *
17
 * eo_do() is invoked with a list of op ids and their parameters and is in charge to dispatch the relevant functions. Finding the correct function is fast because it is just a lookup table.
18
 *
19
 * @section howto How to use it?
20
 * - Creation of an instance of a class
21
 *
22
 *   - Old way:
23
   @code
24
   object = evas_object_line_add(canvas);
25
   @endcode
26
 *
27
 *   - Eo way:
28
   @code
29
   object = eo_add(EVAS_OBJ_LINE_CLASS, canvas);
30
   @endcode
31
 *
32
 * - Call to function
33
 *
34
 *   - Old way:
35
   @code
36
      evas_object_move(obj, 120, 120);
37
      evas_object_resize(obj, 200, 200);
38
   @endcode
39
 *
40
 *   - Eo way:
41
   @code
42
      eo_do(obj,
43
            evas_obj_move(120, 120),
44
            evas_obj_resize(200, 200));
45
   @endcode
46
 *
47
 * - Extract specific data
48
 *
49
 *   - Old way:
50
   @code
51
      Evas_Object_Line *o = (Evas_Object_Line *)(obj->object_data);
52
      MAGIC_CHECK(o, Evas_Object_Line, MAGIC_OBJ_LINE);
53
      return;
54
      MAGIC_CHECK_END();
55
   @endcode
56
 *
57
 *   - Eo way:
58
 *     Two functions can be used to extract object data. The use depends if you want to store the data or not. If you just need to access data in the function (most of the time), just use eo_data_scope_get. If you need to store the data (for example in a list of objects data), you have to use eo_data_ref. This function references the data. If you don't need the referenced data anymore, call eo_data_unref.
59
 *     This reference mechanism will be used in the future to detect bad usage of objects, defragment the memory space used by the objects...
60
   @code
61
      Evas_Object_Line *o = eo_data_scope_get(obj, EVAS_OBJ_LINE_CLASS);
62
      if (!o) return;
63
   @endcode
64
 *    or
65
   @code
66
      Evas_Object_Line *o = eo_data_ref(obj, EVAS_OBJ_LINE_CLASS);
67
      if (!o) return;
68
      ...
69
      eo_data_unref(obj, o);
70
   @endcode
71
 *
72
 * - Call function of parent
73
 *   - Old way:
74
   @code
75
      ELM_WIDGET_CLASS(_elm_button_parent_sc)->theme(obj));
76
   @endcode
77
 *
78
 *   - New way:
79
   @code
80
      eo_do_super(obj, elm_wdg_theme(&int_ret));
81
   @endcode
82
 *
83
 * @section important Important to know
84
 * - eo_do() is the function used to invoke functions of a specific class on an object.
85
 *
86
 * - eo_data_scope_get() and eo_data_ref() receives an object and a class and returns the data of the given class for the object. The class must belong to the object class hierarchy.
87
 *
88
 * - eo_data_unref() receives an object and the data to unreference. The data MUST belong to this object.
89
 *
90
 * - eo_isa() indicates if a given object is of a given type.
91
 *
92
 * - eo_do_super() is in charge to invoke a function in the next parents that implement it. It is recommended to use eo_do_super() only from a function with the same op id.\n
93
 * In addition, there is no way to jump over classes who implement the function. If A inherits from B, B from C and A, B and C implement a virtual function defined in C, the function calls order will be A, then B and finally C. It is impossible to pass over B.
94
 *
95
 * - eo_do() returns if the operation succeeded or failed (function found, object deleted...), not the result of the called function. Pay attention to this detail when you call eo_do(). The return value needs to be an additional parameter which will hold a return value.
96
 *
97
 * - Don't do this:
98
   @code
99
      int w, h;
100
      eo_do(obj,
101
            evas_obj_size_get(&w, &h),
102
            evas_obj_size_set(w+10, h+20));
103
   @endcode
104
 *    w+10 and h+20 are evaluated before the call to size_get.
105
 *    Instead, separate it in two calls to eo_do().
106
 *
107
 * - When creating an object with eo_add(), the reference counter of this one is incremented. If it is called with a parent, two references are on the object. eo_del() removes both of these references.\n
108
 * When there is no more references on an object, this one is deleted and then can be freed. The deletion calls to the destructor (see eo_destructor()). When done, Eo checks if the object can be freed. The free mechanism can be "disabled" through eo_manual_free_set(). If this is the case, it is the responsibility of the developer to call eo_manual_free() on the object in order to free it. This mechanism has been used for example in @ref Evas on the Evas objects and in @ref Ecore.
109
 *
110
 * - When eo_do() reaches a function of a class, it is the responsibility of the user to extract from the va_list ALL the parameters needed for this function, NO MORE, NO LESS. Otherwise, unknown behavior can occur. eo_do() is called with a list of op id, params, op id, params... A bad extraction of parameters can bring to the parsing of a wrong op id and so in the best case, to an error, in the worst case, to another function not in relation with the actual use case.
111
 *
112
 * - Always pay attention to:
113
 *    - the pairing between function id and the function itself. Using the same function for two ids occurs and is hard to debug.
114
 *    - the definition of the function macros in the H file and their parameters order/type
115
 *    - to extract all the parameters of a function from the va_list
116
 *
117
 * - Enum of the op ids in H file and descriptions in C file must be synchronized, i.e same number of ids and same order. If you change the order by adding, removing or moving ids, you break ABI of your library.
118
 *
119
 * - Avoid exposing your class data to prevent ABI break. Supply access functions instead.
120
 *
121
 * @section create_class_h_side How to create a class - H side?
122
 * - If the object is new, establish the public APIs
123
 * - \#define \$(CLASS_NAME) \$(class_name)_class_get(): will be used to access data/inherit from this class...
124
 * - const Eo_Class *\$(class_name)_class_get(void) EINA_CONST: declaration of the function that will create the class (not the instance), i.e virtual table...
125
 * - EAPI extern Eo_Op \$(CLASS_NAME)_BASE_ID: class id that will be essentially used to identify functions set of this class
126
 * - enum of the function ids of the class in the form \$(CLASS_NAME)_SUB_ID: used to identify the function inside the class; function id is unique per class but (class id, function id) is unique per system..
127
 * - \#define \$(CLASS_NAME)_ID(sub_id) (\$(CLASS_NAME)_BASE_ID + sub_id): formula to calculate the system function id
128
 * - define of each function consists of:
129
 *    - the name of the function that will be used in eo_do
130
 *    - parameters without types
131
 *    - \$(CLASS_NAME)_ID(\$(CLASS_NAME)_SUB_ID_FUNCTION
132
 *    - EO_TYPECHECK for each parameter: type and variable name
133
 * - And don't forget to document each function
134
 *
135
 * - Example (Evas Object Line):
136
   @code
137
   #define EVAS_OBJ_LINE_CLASS evas_object_line_class_get()
138

139
   const Eo_Class *evas_object_line_class_get(void) EINA_CONST;
140

141
   EAPI extern Eo_Op EVAS_OBJ_LINE_BASE_ID;
142

143
   enum
144
   {
145
      EVAS_OBJ_LINE_SUB_ID_XY_SET,
146
      EVAS_OBJ_LINE_SUB_ID_XY_GET,
147
      EVAS_OBJ_LINE_SUB_ID_LAST
148
   }
149

150
   #define EVAS_OBJ_LINE_ID(sub_id) (EVAS_OBJ_LINE_BASE_ID + sub_id)
151

152
   /*
153
    * @def evas_obj_line_xy_set
154
    * @since 1.8
155
    *
156
    * Sets the coordinates of the end points of the given evas line object.
157
    *
158
    * @param[in] x1
159
    * @param[in] y1
160
    * @param[in] x2
161
    * @param[in] y2
162
    *
163
    */
164
   #define evas_obj_line_xy_set(x1, y1, x2, y2) EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_SET), EO_TYPECHECK(Evas_Coord, x1), EO_TYPECHECK(Evas_Coord, y1), EO_TYPECHECK(Evas_Coord, x2), EO_TYPECHECK(Evas_Coord, y2)
165

166
   /*
167
    * @def evas_obj_line_xy_get
168
    * @since 1.8
169
    *
170
    * Retrieves the coordinates of the end points of the given evas line object.
171
    *
172
    * @param[out] x1
173
    * @param[out] y1
174
    * @param[out] x2
175
    * @param[out] y2
176
    *
177
    */
178
   #define evas_obj_line_xy_get(x1, y1, x2, y2) EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_GET), EO_TYPECHECK(Evas_Coord *, x1), EO_TYPECHECK(Evas_Coord *, y1), EO_TYPECHECK(Evas_Coord *, x2), EO_TYPECHECK(Evas_Coord *, y2)
179
   @endcode
180
 *
181
 * @section create_class_c_size How to create a class - C side?
182
 * Below, the object line as example.
183
 *
184
   @code
185
   #include "Eo.h"\n
186
   EAPI Eo_Op \$(CLASS_NAME)_BASE_ID = EO_NOOP; // Initialisation of the class id to 0. Will be set dynamically by Eo itself.\n
187
   #define MY_CLASS \$(CLASS_NAME)
188

189
   ...
190
   @endcode
191
 *
192
 * Example for a developer function called by Eo:\n
193
 * This function receives the Eo object, the data corresponding to this class and the list of parameters.
194
   @code
195
   static void
196
   _foo(Eo *eo_obj, void *_pd, va_list *list)
197
   {
198
      int param_1 = va_arg(*list, int);
199
      Eina_Bool param_2 = va_arg(*list, int);
200
      Eina_Bool ret = va_arg(*list, Eina_Bool *);
201
      foo_data obj = _pd;
202

203
      if (ret) *ret = EINA_FALSE;
204
      ...
205
   }
206
   @endcode
207
 *
208
 * You can (not a must) implement a constructor. This constructor MUST call the parent constructor (eo_do_super()). It is the same for the destructor.\n
209
 * See eo_constructor() and eo_destructor().\n
210
 * If you don't have anything to do in constructor (like malloc, variables init...) or in destructor (free), don't implement them.
211
 *
212
 * At the end of the file, you need to describe the class.\n
213
 * First, you need to supply the class constructor that sets the list of the functions that are implemented in this class. It includes functions overriden (constructor, destructor, member_add...) and functions specific to this class. If there is no function implemented in this class, you don't need a class constructor.\n
214
 * Then, you need a list to describe the new functions. For each one, the op id and a description.\n
215
 *
216
 * Then, the class itself that consists in:
217
 *    - the version of Eo, used for backward compatibility
218
 *    - the class name
219
 *    - the type of the class:
220
 *       - regular: an object can be created from this type (mostly used)
221
 *       - regular non instant-iable: Same as previous, but objects can’t be created from this type (elm_widget)
222
 *       - interface: used to extend classes, no implementations for functions and no internal data
223
 *       - mixin : interfaces with internal data and pre-made implementations for functions
224
 *    - the descriptions list described above and the number of ops for this class
225
 *    - events
226
 *    - size of the data of the class
227
 *    - the class constructor, if exists, else NULL
228
 *    - the class destructor (NULL most of the time)
229
 *
230
 * Finally, we define the class with:
231
 *    - the function name to give to the function that creates/returns the class
232
 *    - the class description explained above
233
 *    - the parent and the interfaces/mixins, finished by NULL
234
 *
235
 *
236
 * Example (Evas Object Line):
237
   @code
238
   #include "Eo.h"
239

240
   EAPI Eo_Op EVAS_OBJ_LINE_BASE_ID = EO_NOOP;
241

242
   #define MY_CLASS EVAS_OBJ_LINE_CLASS
243
   @endcode
244
 *
245
 * ...
246
 *
247
   @code
248
   static void
249
   _line_xy_get(Eo *eo_obj, void *_pd, va_list *list)
250
   {
251
      const Evas_Object_Line *o = _pd;
252

253
      Evas_Coord *x1 = va_arg(*list, Evas_Coord *);
254
      Evas_Coord *y1 = va_arg(*list, Evas_Coord *);
255
      Evas_Coord *x2 = va_arg(*list, Evas_Coord *);
256
      Evas_Coord *y2 = va_arg(*list, Evas_Coord *);
257

258
      Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
259
      if (x1) *x1 = obj->cur.geometry.x + o->cur.x1;
260
      if (y1) *y1 = obj->cur.geometry.y + o->cur.y1;
261
      if (x2) *x2 = obj->cur.geometry.x + o->cur.x2;
262
      if (y2) *y2 = obj->cur.geometry.y + o->cur.y2;
263
   }
264

265
   static void
266
   _constructor(Eo *eo_obj, void *class_data, va_list *list EINA_UNUSED)
267
   {
268
      eo_do_super(eo_obj, eo_constructor());
269

270
      Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
271
      evas_object_line_init(eo_obj);
272
   }
273

274
   ...
275

276
   /* class constructor */
277
   static void
278
   _class_constructor(Eo_Class *klass)
279
   {
280
      const Eo_Op_Func_Description func_desc[] = {
281
           /* Virtual functions of parent class implemented in this class */
282
           EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
283
           EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
284
           /* Specific functions to this class */
285
           EO_OP_FUNC(EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_SET), _line_xy_set),
286
           EO_OP_FUNC(EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_GET), _line_xy_get),
287
           EO_OP_FUNC_SENTINEL
288
      };
289

290
      eo_class_funcs_set(klass, func_desc);
291
   }
292

293
   /* Descriptions for the functions specific to this class */
294
   static const Eo_Op_Description op_desc[] = {
295
        EO_OP_DESCRIPTION(EVAS_OBJ_LINE_SUB_ID_XY_SET, "Sets the coordinates of the end points of the given evas line object."),
296
        EO_OP_DESCRIPTION(EVAS_OBJ_LINE_SUB_ID_XY_GET, "Retrieves the coordinates of the end points of the given evas line object."),
297
        EO_OP_DESCRIPTION_SENTINEL
298
   };
299

300
   /* Description of the class */
301
   static const Eo_Class_Description class_desc = {
302
        EO_VERSION,
303
        "Evas_Object_Line",
304
        EO_CLASS_TYPE_REGULAR,
305
        EO_CLASS_DESCRIPTION_OPS(&EVAS_OBJ_LINE_BASE_ID, op_desc, EVAS_OBJ_LINE_SUB_ID_LAST),
306
        NULL,
307
        sizeof(Evas_Object_Line),
308
        _class_constructor,
309
        NULL
310
   };
311

312
   /* Definition of the class */
313
   EO_DEFINE_CLASS(evas_object_line_class_get, &class_desc, EVAS_OBJ_CLASS, NULL);
314
   @endcode
315
 */
316

317

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.