box.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * File : box.c
  3. * This file is part of 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-16 Bernard first version
  13. */
  14. #include <rtgui/dc.h>
  15. #include <rtgui/widgets/box.h>
  16. #ifndef RTGUI_USING_SMALL_SIZE
  17. static void _rtgui_box_constructor(rtgui_box_t *box)
  18. {
  19. /* init widget and set event handler */
  20. rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_box_event_handler);
  21. RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT;
  22. rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_box_event_handler);
  23. /* set proper of control */
  24. box->orient = RTGUI_HORIZONTAL;
  25. box->border_size = RTGUI_BORDER_DEFAULT_WIDTH;
  26. }
  27. DEFINE_CLASS_TYPE(box, "box",
  28. RTGUI_CONTAINER_TYPE,
  29. _rtgui_box_constructor,
  30. RT_NULL,
  31. sizeof(struct rtgui_box));
  32. rt_bool_t rtgui_box_event_handler(struct rtgui_object *widget, rtgui_event_t *event)
  33. {
  34. struct rtgui_box* box = (struct rtgui_box*)widget;
  35. RT_ASSERT(box != RT_NULL);
  36. switch (event->type)
  37. {
  38. case RTGUI_EVENT_RESIZE:
  39. /* re-layout */
  40. rtgui_box_layout(box);
  41. break;
  42. default:
  43. return rtgui_container_event_handler(RTGUI_OBJECT(box), event);
  44. }
  45. return RT_FALSE;
  46. }
  47. struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect)
  48. {
  49. struct rtgui_box* box;
  50. box = (struct rtgui_box*) rtgui_widget_create (RTGUI_BOX_TYPE);
  51. if (box != RT_NULL)
  52. {
  53. /* set proper of control */
  54. rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
  55. box->orient = orientation;
  56. }
  57. return box;
  58. }
  59. void rtgui_box_append(struct rtgui_box* box, rtgui_widget_t* widget)
  60. {
  61. /* put to box's children list */
  62. rtgui_container_add_child(RTGUI_CONTAINER(box), widget);
  63. }
  64. void rtgui_box_delete(struct rtgui_box* box, rtgui_widget_t* widget)
  65. {
  66. /* remove from box's children list */
  67. rtgui_container_remove_child(RTGUI_CONTAINER(box), widget);
  68. }
  69. static void rtgui_box_layout_vertical(rtgui_box_t* box)
  70. {
  71. rtgui_list_t *node;
  72. rt_int32_t box_width;
  73. rt_int32_t space_count;
  74. rt_int32_t next_x, next_y;
  75. rt_int32_t total_height, space_height;
  76. struct rtgui_event_resize size_event;
  77. /* prepare the resize event */
  78. RTGUI_EVENT_RESIZE_INIT(&size_event);
  79. /* find spaces */
  80. space_count = 0;
  81. total_height = 0;
  82. space_height = 0;
  83. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  84. {
  85. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  86. if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
  87. else total_height += widget->mini_height;
  88. }
  89. /* calculate the height for each spaces */
  90. if (space_count != 0)
  91. {
  92. space_height = (rtgui_rect_height(RTGUI_WIDGET(box)->extent) - total_height - (box->border_size << 1)) / space_count;
  93. }
  94. /* init (x, y) and box width */
  95. next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
  96. next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
  97. box_width = rtgui_rect_width(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
  98. /* layout each widget */
  99. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  100. {
  101. rtgui_rect_t *rect;
  102. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  103. /* get extent of widget */
  104. rect = &(widget->extent);
  105. /* reset rect */
  106. rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
  107. rect->x2 = widget->mini_width;
  108. rect->y2 = widget->mini_height;
  109. /* left in default */
  110. rtgui_rect_moveto(rect, next_x, next_y);
  111. if (widget->align & RTGUI_ALIGN_EXPAND)
  112. {
  113. /* expand on horizontal */
  114. rect->x2 = rect->x1 + (rt_int16_t)box_width;
  115. }
  116. if (widget->align & RTGUI_ALIGN_CENTER_VERTICAL)
  117. {
  118. /* center */
  119. rt_uint32_t mid;
  120. mid = box_width - rtgui_rect_width(*rect);
  121. mid = mid /2;
  122. rect->x1 = next_x + mid;
  123. rect->x2 = next_x + box_width - mid;
  124. }
  125. else if (widget->align & RTGUI_ALIGN_RIGHT)
  126. {
  127. /* right */
  128. rect->x1 = next_x + box_width - rtgui_rect_width(*rect);
  129. rect->x2 = next_x + box_width;
  130. }
  131. if (widget->align & RTGUI_ALIGN_STRETCH)
  132. {
  133. rect->y2 = rect->y1 + space_height;
  134. }
  135. /* process resize event */
  136. size_event.x = rect->x1;
  137. size_event.y = rect->y1;
  138. size_event.w = rect->x2 - rect->x1;
  139. size_event.h = rect->y2 - rect->y1;
  140. RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
  141. &size_event.parent);
  142. /* point to next height */
  143. next_y = rect->y2;
  144. }
  145. }
  146. static void rtgui_box_layout_horizontal(rtgui_box_t* box)
  147. {
  148. rtgui_list_t *node;
  149. rt_int32_t box_height;
  150. rt_int32_t space_count;
  151. rt_int32_t next_x, next_y;
  152. rt_int32_t total_width, space_width;
  153. struct rtgui_event_resize size_event;
  154. /* prepare the resize event */
  155. RTGUI_EVENT_RESIZE_INIT(&size_event);
  156. /* find spaces */
  157. space_count = 0;
  158. total_width = 0;
  159. space_width = 0;
  160. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  161. {
  162. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  163. if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
  164. else total_width += widget->mini_width;
  165. }
  166. if (space_count != 0)
  167. {
  168. /* calculate the height for each spaces */
  169. space_width = (rtgui_rect_width(RTGUI_WIDGET(box)->extent) - total_width) / space_count;
  170. }
  171. /* init (x, y) and box height */
  172. next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
  173. next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
  174. box_height = rtgui_rect_height(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
  175. /* layout each widget */
  176. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  177. {
  178. rtgui_rect_t *rect;
  179. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  180. /* get extent of widget */
  181. rect = &(widget->extent);
  182. /* reset rect */
  183. rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
  184. rect->x2 = widget->mini_width;
  185. rect->y2 = widget->mini_height;
  186. /* top in default */
  187. rtgui_rect_moveto(rect, next_x, next_y);
  188. if (widget->align & RTGUI_ALIGN_EXPAND)
  189. {
  190. /* expand on vertical */
  191. rect->y2 = rect->y1 + box_height;
  192. }
  193. if (widget->align & RTGUI_ALIGN_CENTER_HORIZONTAL)
  194. {
  195. /* center */
  196. rt_uint32_t mid;
  197. mid = box_height - rtgui_rect_height(*rect);
  198. mid = mid /2;
  199. rect->y1 = next_y + mid;
  200. rect->y2 = next_y + box_height - mid;
  201. }
  202. else if (widget->align & RTGUI_ALIGN_RIGHT)
  203. {
  204. /* right */
  205. rect->y1 = next_y + box_height - rtgui_rect_height(*rect);
  206. rect->y2 = next_y + box_height;
  207. }
  208. if (widget->align & RTGUI_ALIGN_STRETCH)
  209. {
  210. rect->x2 = rect->x1 + space_width;
  211. }
  212. /* process resize event */
  213. size_event.x = rect->x1;
  214. size_event.y = rect->y1;
  215. size_event.w = rect->x2 - rect->x1;
  216. size_event.h = rect->y2 - rect->y1;
  217. RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
  218. &size_event.parent);
  219. /* point to next width */
  220. next_x = rect->x2;
  221. }
  222. }
  223. void rtgui_box_layout(rtgui_box_t* box)
  224. {
  225. RT_ASSERT(box != RT_NULL);
  226. if (box->orient & RTGUI_VERTICAL)
  227. {
  228. rtgui_box_layout_vertical(box);
  229. }
  230. else
  231. {
  232. rtgui_box_layout_horizontal(box);
  233. }
  234. /* update box and its children clip */
  235. if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box)))
  236. {
  237. rtgui_widget_update_clip(RTGUI_WIDGET(box));
  238. }
  239. }
  240. rt_uint32_t rtgui_box_get_width(rtgui_box_t* box)
  241. {
  242. rtgui_list_t *node;
  243. rt_uint32_t width;
  244. width = 0;
  245. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  246. {
  247. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  248. rt_uint32_t widget_width;
  249. widget_width = rtgui_rect_width(widget->extent);
  250. if (box->orient & RTGUI_VERTICAL)
  251. {
  252. /* get the max width */
  253. if (width < widget_width) width = widget_width;
  254. }
  255. else
  256. {
  257. /* get the total width */
  258. width += widget_width;
  259. }
  260. }
  261. return width;
  262. }
  263. rt_uint32_t rtgui_box_get_height(rtgui_box_t* box)
  264. {
  265. rtgui_list_t *node;
  266. rt_uint32_t height;
  267. height = 0;
  268. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  269. {
  270. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  271. rt_uint32_t widget_height;
  272. widget_height = rtgui_rect_height(widget->extent);
  273. if (box->orient & RTGUI_HORIZONTAL)
  274. {
  275. /* get the max height */
  276. if (height < widget_height) height = widget_height;
  277. }
  278. else
  279. {
  280. /* get the total height */
  281. height += widget_height;
  282. }
  283. }
  284. return height;
  285. }
  286. #endif