rtgui_object.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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(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(rtgui_type_t *type, rtgui_object_t *object)
  39. {
  40. while (type)
  41. {
  42. if (type->destructor) type->destructor(object);
  43. type = type->parent;
  44. }
  45. }
  46. rt_bool_t rtgui_type_inherits_from(rtgui_type_t *type, rtgui_type_t *parent)
  47. {
  48. while (type)
  49. {
  50. if (type == parent) return RT_TRUE;
  51. type = type->parent;
  52. }
  53. return RT_FALSE;
  54. }
  55. rtgui_type_t *rtgui_type_parent_type_get(rtgui_type_t *type)
  56. {
  57. return type->parent;
  58. }
  59. const char *rtgui_type_name_get(rtgui_type_t *type)
  60. {
  61. if (!type) return RT_NULL;
  62. return type->name;
  63. }
  64. #ifdef RTGUI_OBJECT_TRACE
  65. struct rtgui_object_information
  66. {
  67. rt_uint32_t objs_number;
  68. rt_uint32_t allocated_size;
  69. rt_uint32_t max_allocated;
  70. };
  71. struct rtgui_object_information obj_info = {0, 0, 0};
  72. #endif
  73. /**
  74. * @brief Creates a new object: it calls the corresponding constructors (from the constructor of the base class to the
  75. * constructor of the more derived class) and then sets the values of the given properties
  76. * @param object_type the type of object to create
  77. * @return Returns the new Etk_Object of type @a object_type
  78. */
  79. rtgui_object_t *rtgui_object_create(rtgui_type_t *object_type)
  80. {
  81. rtgui_object_t *new_object;
  82. if (!object_type)
  83. return RT_NULL;
  84. new_object = rtgui_malloc(object_type->size);
  85. if (new_object == RT_NULL) return RT_NULL;
  86. #ifdef RTGUI_OBJECT_TRACE
  87. obj_info.objs_number ++;
  88. obj_info.allocated_size += object_type->size;
  89. if (obj_info.allocated_size > obj_info.max_allocated)
  90. obj_info.max_allocated = obj_info.allocated_size;
  91. #endif
  92. new_object->type = object_type;
  93. new_object->is_static = RT_FALSE;
  94. rtgui_type_object_construct(object_type, new_object);
  95. return new_object;
  96. }
  97. /**
  98. * @brief Destroys the object: it first sets the weak-pointers to RT_NULL, emits the "destroyed" signal, and then
  99. * queues the object in the list of objects to free. Thus, the destructors will only be called at the beginning of the
  100. * next main loop iteration (from the destructor of the more derived class to the destructor of the ultimate base class).
  101. * @param object the object to destroy
  102. * @warning You should not assume that this function will call directly the destructors of the object!
  103. */
  104. void rtgui_object_destroy(rtgui_object_t *object)
  105. {
  106. if (!object || object->is_static == RT_TRUE) return;
  107. #ifdef RTGUI_OBJECT_TRACE
  108. obj_info.objs_number --;
  109. obj_info.allocated_size -= object->type->size;
  110. #endif
  111. /* call destructor */
  112. RT_ASSERT(object->type != RT_NULL);
  113. rtgui_type_destructors_call(object->type, object);
  114. /* release object */
  115. rtgui_free(object);
  116. }
  117. /**
  118. * @brief Checks if @a object can be cast to @a type.
  119. * If @a object doesn't inherit from @a type, a warning is displayed in the console but the object is returned anyway.
  120. * @param object the object to cast
  121. * @param type the type to which we cast the object
  122. * @return Returns the object
  123. * @note You usually do not need to call this function, use specific macros instead (ETK_IS_WIDGET() for example)
  124. */
  125. rtgui_object_t *rtgui_object_check_cast(rtgui_object_t *obj, rtgui_type_t *obj_type)
  126. {
  127. if (!obj) return RT_NULL;
  128. if (!rtgui_type_inherits_from(obj->type, obj_type))
  129. {
  130. rt_kprintf("Invalid cast from \"%s\" to \"%s\"\n", rtgui_type_name_get(obj->type), rtgui_type_name_get(obj_type));
  131. }
  132. return obj;
  133. }
  134. /**
  135. * @brief Gets the type of the object
  136. * @param object an object
  137. * @return Returns the type of @a object (RT_NULL on failure)
  138. */
  139. rtgui_type_t *rtgui_object_object_type_get(rtgui_object_t *object)
  140. {
  141. if (!object) return RT_NULL;
  142. return object->type;
  143. }