1
0

box.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. rtgui_type_t *rtgui_box_type_get(void)
  28. {
  29. static rtgui_type_t *box_type = RT_NULL;
  30. if (!box_type)
  31. {
  32. box_type = rtgui_type_create("box", RTGUI_CONTAINER_TYPE,
  33. sizeof(rtgui_box_t), RTGUI_CONSTRUCTOR(_rtgui_box_constructor), RT_NULL);
  34. }
  35. return box_type;
  36. }
  37. rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event)
  38. {
  39. struct rtgui_box* box = (struct rtgui_box*)widget;
  40. RT_ASSERT(box != RT_NULL);
  41. switch (event->type)
  42. {
  43. case RTGUI_EVENT_RESIZE:
  44. /* re-layout */
  45. rtgui_box_layout(box);
  46. break;
  47. default:
  48. return rtgui_container_event_handler(RTGUI_WIDGET(box), event);
  49. }
  50. return RT_FALSE;
  51. }
  52. struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect)
  53. {
  54. struct rtgui_box* box;
  55. box = (struct rtgui_box*) rtgui_widget_create (RTGUI_BOX_TYPE);
  56. if (box != RT_NULL)
  57. {
  58. /* set proper of control */
  59. rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
  60. box->orient = orientation;
  61. }
  62. return box;
  63. }
  64. void rtgui_box_append(struct rtgui_box* box, rtgui_widget_t* widget)
  65. {
  66. /* put to box's children list */
  67. rtgui_container_add_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. widget->event_handler(widget, &size_event.parent);
  141. /* point to next height */
  142. next_y = rect->y2;
  143. }
  144. }
  145. static void rtgui_box_layout_horizontal(rtgui_box_t* box)
  146. {
  147. rtgui_list_t *node;
  148. rt_int32_t box_height;
  149. rt_int32_t space_count;
  150. rt_int32_t next_x, next_y;
  151. rt_int32_t total_width, space_width;
  152. struct rtgui_event_resize size_event;
  153. /* prepare the resize event */
  154. RTGUI_EVENT_RESIZE_INIT(&size_event);
  155. /* find spaces */
  156. space_count = 0;
  157. total_width = 0;
  158. space_width = 0;
  159. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  160. {
  161. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  162. if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
  163. else total_width += widget->mini_width;
  164. }
  165. if (space_count != 0)
  166. {
  167. /* calculate the height for each spaces */
  168. space_width = (rtgui_rect_width(RTGUI_WIDGET(box)->extent) - total_width) / space_count;
  169. }
  170. /* init (x, y) and box height */
  171. next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
  172. next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
  173. box_height = rtgui_rect_height(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
  174. /* layout each widget */
  175. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  176. {
  177. rtgui_rect_t *rect;
  178. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  179. /* get extent of widget */
  180. rect = &(widget->extent);
  181. /* reset rect */
  182. rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
  183. rect->x2 = widget->mini_width;
  184. rect->y2 = widget->mini_height;
  185. /* top in default */
  186. rtgui_rect_moveto(rect, next_x, next_y);
  187. if (widget->align & RTGUI_ALIGN_EXPAND)
  188. {
  189. /* expand on vertical */
  190. rect->y2 = rect->y1 + box_height;
  191. }
  192. if (widget->align & RTGUI_ALIGN_CENTER_HORIZONTAL)
  193. {
  194. /* center */
  195. rt_uint32_t mid;
  196. mid = box_height - rtgui_rect_height(*rect);
  197. mid = mid /2;
  198. rect->y1 = next_y + mid;
  199. rect->y2 = next_y + box_height - mid;
  200. }
  201. else if (widget->align & RTGUI_ALIGN_RIGHT)
  202. {
  203. /* right */
  204. rect->y1 = next_y + box_height - rtgui_rect_height(*rect);
  205. rect->y2 = next_y + box_height;
  206. }
  207. if (widget->align & RTGUI_ALIGN_STRETCH)
  208. {
  209. rect->x2 = rect->x1 + space_width;
  210. }
  211. /* process resize event */
  212. size_event.x = rect->x1;
  213. size_event.y = rect->y1;
  214. size_event.w = rect->x2 - rect->x1;
  215. size_event.h = rect->y2 - rect->y1;
  216. widget->event_handler(widget, &size_event.parent);
  217. /* point to next width */
  218. next_x = rect->x2;
  219. }
  220. }
  221. void rtgui_box_layout(rtgui_box_t* box)
  222. {
  223. RT_ASSERT(box != RT_NULL);
  224. if (box->orient & RTGUI_VERTICAL)
  225. {
  226. rtgui_box_layout_vertical(box);
  227. }
  228. else
  229. {
  230. rtgui_box_layout_horizontal(box);
  231. }
  232. /* update box and its children clip */
  233. if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box)))
  234. {
  235. rtgui_widget_update_clip(RTGUI_WIDGET(box));
  236. }
  237. }
  238. rt_uint32_t rtgui_box_get_width(rtgui_box_t* box)
  239. {
  240. rtgui_list_t *node;
  241. rt_uint32_t width;
  242. width = 0;
  243. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  244. {
  245. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  246. rt_uint32_t widget_width;
  247. widget_width = rtgui_rect_width(widget->extent);
  248. if (box->orient & RTGUI_VERTICAL)
  249. {
  250. /* get the max width */
  251. if (width < widget_width) width = widget_width;
  252. }
  253. else
  254. {
  255. /* get the total width */
  256. width += widget_width;
  257. }
  258. }
  259. return width;
  260. }
  261. rt_uint32_t rtgui_box_get_height(rtgui_box_t* box)
  262. {
  263. rtgui_list_t *node;
  264. rt_uint32_t height;
  265. height = 0;
  266. rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
  267. {
  268. rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
  269. rt_uint32_t widget_height;
  270. widget_height = rtgui_rect_height(widget->extent);
  271. if (box->orient & RTGUI_HORIZONTAL)
  272. {
  273. /* get the max height */
  274. if (height < widget_height) height = widget_height;
  275. }
  276. else
  277. {
  278. /* get the total height */
  279. height += widget_height;
  280. }
  281. }
  282. return height;
  283. }
  284. #endif