box.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler);
  21. RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT;
  22. rtgui_widget_set_event_handler(RTGUI_WIDGET(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(rtgui_widget_t* 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_WIDGET(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. static void rtgui_box_layout_vertical(rtgui_box_t* box)
  65. {
  66. rtgui_list_t *node;
  67. rt_int32_t box_width;
  68. rt_int32_t space_count;
  69. rt_int32_t next_x, next_y;
  70. rt_int32_t total_height, space_height;
  71. struct rtgui_event_resize size_event;
  72. /* prepare the resize event */
  73. RTGUI_EVENT_RESIZE_INIT(&size_event);
  74. /* find spaces */
  75. space_count = 0;
  76. total_height = 0;
  77. space_height = 0;
  78. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  79. {
  80. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  81. if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
  82. else total_height += widget->mini_height;
  83. }
  84. /* calculate the height for each spaces */
  85. if (space_count != 0)
  86. {
  87. space_height = (rtgui_rect_height(RTGUI_WIDGET(box)->extent) - total_height - (box->border_size << 1)) / space_count;
  88. }
  89. /* init (x, y) and box width */
  90. next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
  91. next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
  92. box_width = rtgui_rect_width(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
  93. /* layout each widget */
  94. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  95. {
  96. rtgui_rect_t *rect;
  97. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  98. /* get extent of widget */
  99. rect = &(widget->extent);
  100. /* reset rect */
  101. rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
  102. rect->x2 = widget->mini_width;
  103. rect->y2 = widget->mini_height;
  104. /* left in default */
  105. rtgui_rect_moveto(rect, next_x, next_y);
  106. if (widget->align & RTGUI_ALIGN_EXPAND)
  107. {
  108. /* expand on horizontal */
  109. rect->x2 = rect->x1 + (rt_int16_t)box_width;
  110. }
  111. if (widget->align & RTGUI_ALIGN_CENTER_VERTICAL)
  112. {
  113. /* center */
  114. rt_uint32_t mid;
  115. mid = box_width - rtgui_rect_width(*rect);
  116. mid = mid /2;
  117. rect->x1 = next_x + mid;
  118. rect->x2 = next_x + box_width - mid;
  119. }
  120. else if (widget->align & RTGUI_ALIGN_RIGHT)
  121. {
  122. /* right */
  123. rect->x1 = next_x + box_width - rtgui_rect_width(*rect);
  124. rect->x2 = next_x + box_width;
  125. }
  126. if (widget->align & RTGUI_ALIGN_STRETCH)
  127. {
  128. rect->y2 = rect->y1 + space_height;
  129. }
  130. /* process resize event */
  131. size_event.x = rect->x1;
  132. size_event.y = rect->y1;
  133. size_event.w = rect->x2 - rect->x1;
  134. size_event.h = rect->y2 - rect->y1;
  135. widget->event_handler(widget, &size_event.parent);
  136. /* point to next height */
  137. next_y = rect->y2;
  138. }
  139. }
  140. static void rtgui_box_layout_horizontal(rtgui_box_t* box)
  141. {
  142. rtgui_list_t *node;
  143. rt_int32_t box_height;
  144. rt_int32_t space_count;
  145. rt_int32_t next_x, next_y;
  146. rt_int32_t total_width, space_width;
  147. struct rtgui_event_resize size_event;
  148. /* prepare the resize event */
  149. RTGUI_EVENT_RESIZE_INIT(&size_event);
  150. /* find spaces */
  151. space_count = 0;
  152. total_width = 0;
  153. space_width = 0;
  154. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  155. {
  156. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  157. if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
  158. else total_width += widget->mini_width;
  159. }
  160. if (space_count != 0)
  161. {
  162. /* calculate the height for each spaces */
  163. space_width = (rtgui_rect_width(RTGUI_WIDGET(box)->extent) - total_width) / space_count;
  164. }
  165. /* init (x, y) and box height */
  166. next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
  167. next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
  168. box_height = rtgui_rect_height(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
  169. /* layout each widget */
  170. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  171. {
  172. rtgui_rect_t *rect;
  173. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  174. /* get extent of widget */
  175. rect = &(widget->extent);
  176. /* reset rect */
  177. rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
  178. rect->x2 = widget->mini_width;
  179. rect->y2 = widget->mini_height;
  180. /* top in default */
  181. rtgui_rect_moveto(rect, next_x, next_y);
  182. if (widget->align & RTGUI_ALIGN_EXPAND)
  183. {
  184. /* expand on vertical */
  185. rect->y2 = rect->y1 + box_height;
  186. }
  187. if (widget->align & RTGUI_ALIGN_CENTER_HORIZONTAL)
  188. {
  189. /* center */
  190. rt_uint32_t mid;
  191. mid = box_height - rtgui_rect_height(*rect);
  192. mid = mid /2;
  193. rect->y1 = next_y + mid;
  194. rect->y2 = next_y + box_height - mid;
  195. }
  196. else if (widget->align & RTGUI_ALIGN_RIGHT)
  197. {
  198. /* right */
  199. rect->y1 = next_y + box_height - rtgui_rect_height(*rect);
  200. rect->y2 = next_y + box_height;
  201. }
  202. if (widget->align & RTGUI_ALIGN_STRETCH)
  203. {
  204. rect->x2 = rect->x1 + space_width;
  205. }
  206. /* process resize event */
  207. size_event.x = rect->x1;
  208. size_event.y = rect->y1;
  209. size_event.w = rect->x2 - rect->x1;
  210. size_event.h = rect->y2 - rect->y1;
  211. widget->event_handler(widget, &size_event.parent);
  212. /* point to next width */
  213. next_x = rect->x2;
  214. }
  215. }
  216. void rtgui_box_layout(rtgui_box_t* box)
  217. {
  218. RT_ASSERT(box != RT_NULL);
  219. if (box->orient & RTGUI_VERTICAL)
  220. {
  221. rtgui_box_layout_vertical(box);
  222. }
  223. else
  224. {
  225. rtgui_box_layout_horizontal(box);
  226. }
  227. /* update box and its children clip */
  228. if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box)))
  229. {
  230. rtgui_widget_update_clip(RTGUI_WIDGET(box));
  231. }
  232. }
  233. rt_uint32_t rtgui_box_get_width(rtgui_box_t* box)
  234. {
  235. rtgui_list_t *node;
  236. rt_uint32_t width;
  237. width = 0;
  238. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  239. {
  240. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  241. rt_uint32_t widget_width;
  242. widget_width = rtgui_rect_width(widget->extent);
  243. if (box->orient & RTGUI_VERTICAL)
  244. {
  245. /* get the max width */
  246. if (width < widget_width) width = widget_width;
  247. }
  248. else
  249. {
  250. /* get the total width */
  251. width += widget_width;
  252. }
  253. }
  254. return width;
  255. }
  256. rt_uint32_t rtgui_box_get_height(rtgui_box_t* box)
  257. {
  258. rtgui_list_t *node;
  259. rt_uint32_t height;
  260. height = 0;
  261. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  262. {
  263. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  264. rt_uint32_t widget_height;
  265. widget_height = rtgui_rect_height(widget->extent);
  266. if (box->orient & RTGUI_HORIZONTAL)
  267. {
  268. /* get the max height */
  269. if (height < widget_height) height = widget_height;
  270. }
  271. else
  272. {
  273. /* get the total height */
  274. height += widget_height;
  275. }
  276. }
  277. return height;
  278. }
  279. #endif