1
0

rtgui_object.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * File : rtgui_object.c
  3. * This file is part of RTGUI in RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2009-10-04 Bernard first version
  13. */
  14. #include <rtgui/rtgui_object.h>
  15. #include <rtgui/rtgui_system.h>
  16. static void _rtgui_object_constructor(rtgui_object_t *object)
  17. {
  18. if (!object) return;
  19. object->is_static = RT_FALSE;
  20. }
  21. /* Destroys the object */
  22. static void _rtgui_object_destructor(rtgui_object_t *object)
  23. {
  24. /* nothing */
  25. }
  26. DEFINE_CLASS_TYPE(type, "object",
  27. RT_NULL,
  28. _rtgui_object_constructor,
  29. _rtgui_object_destructor,
  30. sizeof(struct rtgui_object));
  31. void rtgui_type_object_construct(const rtgui_type_t *type, rtgui_object_t *object)
  32. {
  33. /* first call parent's type */
  34. if (type->parent != RT_NULL)
  35. rtgui_type_object_construct(type->parent, object);
  36. if (type->constructor) type->constructor(object);
  37. }
  38. void rtgui_type_destructors_call(const rtgui_type_t *type, rtgui_object_t *object)
  39. {
  40. const rtgui_type_t *t;
  41. t = type;
  42. while (t)
  43. {
  44. if (t->destructor) t->destructor(object);
  45. t = t->parent;
  46. }
  47. }
  48. rt_bool_t rtgui_type_inherits_from(const rtgui_type_t *type, const rtgui_type_t *parent)
  49. {
  50. const rtgui_type_t *t;
  51. t = type;
  52. while (t)
  53. {
  54. if (t == parent) return RT_TRUE;
  55. t = t->parent;
  56. }
  57. return RT_FALSE;
  58. }
  59. const rtgui_type_t *rtgui_type_parent_type_get(const rtgui_type_t *type)
  60. {
  61. return type->parent;
  62. }
  63. const char *rtgui_type_name_get(const rtgui_type_t *type)
  64. {
  65. if (!type) return RT_NULL;
  66. return type->name;
  67. }
  68. #ifdef RTGUI_OBJECT_TRACE
  69. struct rtgui_object_information
  70. {
  71. rt_uint32_t objs_number;
  72. rt_uint32_t allocated_size;
  73. rt_uint32_t max_allocated;
  74. };
  75. struct rtgui_object_information obj_info = {0, 0, 0};
  76. #endif
  77. /**
  78. * @brief Creates a new object: it calls the corresponding constructors (from the constructor of the base class to the
  79. * constructor of the more derived class) and then sets the values of the given properties
  80. * @param object_type the type of object to create
  81. * @return Returns the new Etk_Object of type @a object_type
  82. */
  83. rtgui_object_t *rtgui_object_create(rtgui_type_t *object_type)
  84. {
  85. rtgui_object_t *new_object;
  86. if (!object_type)
  87. return RT_NULL;
  88. new_object = rtgui_malloc(object_type->size);
  89. if (new_object == RT_NULL) return RT_NULL;
  90. #ifdef RTGUI_OBJECT_TRACE
  91. obj_info.objs_number ++;
  92. obj_info.allocated_size += object_type->size;
  93. if (obj_info.allocated_size > obj_info.max_allocated)
  94. obj_info.max_allocated = obj_info.allocated_size;
  95. #endif
  96. new_object->type = object_type;
  97. new_object->is_static = RT_FALSE;
  98. rtgui_type_object_construct(object_type, new_object);
  99. return new_object;
  100. }
  101. /**
  102. * @brief Destroys the object: it first sets the weak-pointers to RT_NULL, emits the "destroyed" signal, and then
  103. * queues the object in the list of objects to free. Thus, the destructors will only be called at the beginning of the
  104. * next main loop iteration (from the destructor of the more derived class to the destructor of the ultimate base class).
  105. * @param object the object to destroy
  106. * @warning You should not assume that this function will call directly the destructors of the object!
  107. */
  108. void rtgui_object_destroy(rtgui_object_t *object)
  109. {
  110. if (!object || object->is_static == RT_TRUE) return;
  111. #ifdef RTGUI_OBJECT_TRACE
  112. obj_info.objs_number --;
  113. obj_info.allocated_size -= object->type->size;
  114. #endif
  115. /* call destructor */
  116. RT_ASSERT(object->type != RT_NULL);
  117. rtgui_type_destructors_call(object->type, object);
  118. /* release object */
  119. rtgui_free(object);
  120. }
  121. /**
  122. * @brief Checks if @a object can be cast to @a type.
  123. * If @a object doesn't inherit from @a type, a warning is displayed in the console but the object is returned anyway.
  124. * @param object the object to cast
  125. * @param type the type to which we cast the object
  126. * @return Returns the object
  127. * @note You usually do not need to call this function, use specific macros instead (ETK_IS_WIDGET() for example)
  128. */
  129. rtgui_object_t *rtgui_object_check_cast(rtgui_object_t *obj, rtgui_type_t *obj_type)
  130. {
  131. if (!obj) return RT_NULL;
  132. if (!rtgui_type_inherits_from(obj->type, obj_type))
  133. {
  134. rt_kprintf("Invalid cast from \"%s\" to \"%s\"\n", rtgui_type_name_get(obj->type), rtgui_type_name_get(obj_type));
  135. }
  136. return obj;
  137. }
  138. /**
  139. * @brief Gets the type of the object
  140. * @param object an object
  141. * @return Returns the type of @a object (RT_NULL on failure)
  142. */
  143. const rtgui_type_t *rtgui_object_object_type_get(rtgui_object_t *object)
  144. {
  145. if (!object) return RT_NULL;
  146. return object->type;
  147. }