widget.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. /*
  2. * File : widget.c
  3. * This file is part of RT-Thread GUI Engine
  4. * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2009-10-04 Bernard first version
  23. * 2010-06-26 Bernard add user_data to widget structure
  24. * 2013-10-07 Bernard remove the win_check in update_clip.
  25. */
  26. #include <string.h>
  27. #include <rtgui/dc.h>
  28. #include <rtgui/rtgui_app.h>
  29. #include <rtgui/widgets/widget.h>
  30. #include <rtgui/widgets/window.h>
  31. #include <rtgui/widgets/container.h>
  32. static void _rtgui_widget_constructor(rtgui_widget_t *widget)
  33. {
  34. if (!widget) return;
  35. /* set widget as shown */
  36. widget->flag = RTGUI_WIDGET_FLAG_SHOWN;
  37. /* init list */
  38. rtgui_list_init(&(widget->sibling));
  39. /* init gc */
  40. widget->gc.foreground = default_foreground;
  41. widget->gc.background = default_background;
  42. widget->gc.font = rtgui_font_default();
  43. widget->gc.textstyle = RTGUI_TEXTSTYLE_NORMAL;
  44. widget->gc.textalign = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
  45. widget->align = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
  46. /* clear the garbage value of extent and clip */
  47. memset(&(widget->extent), 0x0, sizeof(widget->extent));
  48. memset(&(widget->extent_visiable), 0x0, sizeof(widget->extent_visiable));
  49. widget->min_width = widget->min_height = 0;
  50. rtgui_region_init_with_extents(&widget->clip, &widget->extent);
  51. /* set parent and toplevel root */
  52. widget->parent = RT_NULL;
  53. widget->toplevel = RT_NULL;
  54. /* some common event handler */
  55. widget->on_focus_in = RT_NULL;
  56. widget->on_focus_out = RT_NULL;
  57. /* set default event handler */
  58. rtgui_object_set_event_handler(RTGUI_OBJECT(widget), rtgui_widget_event_handler);
  59. /* init user data private to 0 */
  60. widget->user_data = 0;
  61. /* init hardware dc */
  62. rtgui_dc_client_init(widget);
  63. }
  64. /* Destroys the widget */
  65. static void _rtgui_widget_destructor(rtgui_widget_t *widget)
  66. {
  67. if (widget == RT_NULL) return;
  68. if (widget->parent != RT_NULL && RTGUI_IS_CONTAINER(widget->parent))
  69. {
  70. /* remove widget from parent's children list */
  71. rtgui_list_remove(&(RTGUI_CONTAINER(widget->parent)->children), &(widget->sibling));
  72. widget->parent = RT_NULL;
  73. }
  74. /* fini clip region */
  75. rtgui_region_fini(&(widget->clip));
  76. }
  77. DEFINE_CLASS_TYPE(widget, "widget",
  78. RTGUI_PARENT_TYPE(object),
  79. _rtgui_widget_constructor,
  80. _rtgui_widget_destructor,
  81. sizeof(struct rtgui_widget));
  82. RTM_EXPORT(_rtgui_widget);
  83. rtgui_widget_t *rtgui_widget_create(const rtgui_type_t *widget_type)
  84. {
  85. struct rtgui_widget *widget;
  86. widget = RTGUI_WIDGET(rtgui_object_create(widget_type));
  87. return widget;
  88. }
  89. RTM_EXPORT(rtgui_widget_create);
  90. void rtgui_widget_destroy(rtgui_widget_t *widget)
  91. {
  92. rtgui_object_destroy(RTGUI_OBJECT(widget));
  93. }
  94. RTM_EXPORT(rtgui_widget_destroy);
  95. void rtgui_widget_set_rect(rtgui_widget_t *widget, const rtgui_rect_t *rect)
  96. {
  97. int delta_x, delta_y;
  98. if (widget == RT_NULL || rect == RT_NULL) return;
  99. /* update extent rectangle */
  100. widget->extent = *rect;
  101. /* set the visiable extern as extern */
  102. widget->extent_visiable = *rect;
  103. if (RTGUI_IS_CONTAINER(widget))
  104. {
  105. /* re-do layout */
  106. rtgui_container_layout(RTGUI_CONTAINER(widget));
  107. }
  108. /* reset min width and height */
  109. widget->min_width = rtgui_rect_width(widget->extent);
  110. widget->min_height = rtgui_rect_height(widget->extent);
  111. /* it's not empty, fini it */
  112. if (rtgui_region_not_empty(&(widget->clip)))
  113. {
  114. rtgui_region_fini(&(widget->clip));
  115. }
  116. /* reset clip info */
  117. rtgui_region_init_with_extents(&(widget->clip), rect);
  118. if ((widget->parent != RT_NULL) && (widget->toplevel != RT_NULL))
  119. {
  120. if ((void*)widget->parent == (void*)widget->toplevel)
  121. {
  122. rtgui_win_update_clip(widget->toplevel);
  123. }
  124. else
  125. {
  126. /* update widget clip */
  127. rtgui_widget_update_clip(widget->parent);
  128. }
  129. }
  130. /* move to a logic position if it's a container widget */
  131. if (RTGUI_IS_CONTAINER(widget))
  132. {
  133. delta_x = rect->x1 - widget->extent.x1;
  134. delta_y = rect->y1 - widget->extent.y1;
  135. rtgui_widget_move_to_logic(widget, delta_x, delta_y);
  136. }
  137. }
  138. RTM_EXPORT(rtgui_widget_set_rect);
  139. void rtgui_widget_set_rectangle(rtgui_widget_t *widget, int x, int y, int width, int height)
  140. {
  141. rtgui_rect_t rect;
  142. rect.x1 = x;
  143. rect.y1 = y;
  144. rect.x2 = x + width;
  145. rect.y2 = y + height;
  146. rtgui_widget_set_rect(widget, &rect);
  147. }
  148. RTM_EXPORT(rtgui_widget_set_rectangle);
  149. void rtgui_widget_set_parent(rtgui_widget_t *widget, rtgui_widget_t *parent)
  150. {
  151. /* set parent and toplevel widget */
  152. widget->parent = parent;
  153. }
  154. RTM_EXPORT(rtgui_widget_set_parent);
  155. void rtgui_widget_get_extent(rtgui_widget_t *widget, rtgui_rect_t *rect)
  156. {
  157. RT_ASSERT(widget != RT_NULL);
  158. RT_ASSERT(rect != RT_NULL);
  159. *rect = widget->extent;
  160. }
  161. RTM_EXPORT(rtgui_widget_get_extent);
  162. void rtgui_widget_set_minsize(rtgui_widget_t *widget, int width, int height)
  163. {
  164. RT_ASSERT(widget != RT_NULL);
  165. widget->min_width = width;
  166. widget->min_height = height;
  167. }
  168. RTM_EXPORT(rtgui_widget_set_minsize);
  169. void rtgui_widget_set_minwidth(rtgui_widget_t *widget, int width)
  170. {
  171. RT_ASSERT(widget != RT_NULL);
  172. widget->min_width = width;
  173. }
  174. RTM_EXPORT(rtgui_widget_set_minwidth);
  175. void rtgui_widget_set_minheight(rtgui_widget_t *widget, int height)
  176. {
  177. RT_ASSERT(widget != RT_NULL);
  178. widget->min_height = height;
  179. }
  180. RTM_EXPORT(rtgui_widget_set_minheight);
  181. static void _widget_move(struct rtgui_widget* widget, int dx, int dy)
  182. {
  183. struct rtgui_list_node *node;
  184. rtgui_widget_t *child, *parent;
  185. rtgui_rect_move(&(widget->extent), dx, dy);
  186. /* handle visiable extent */
  187. widget->extent_visiable = widget->extent;
  188. parent = widget->parent;
  189. /* we should find out the none-transparent parent */
  190. while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
  191. if (widget->parent)
  192. rtgui_rect_intersect(&(widget->parent->extent_visiable), &(widget->extent_visiable));
  193. /* reset clip info */
  194. rtgui_region_init_with_extents(&(widget->clip), &(widget->extent));
  195. /* move each child */
  196. if (RTGUI_IS_CONTAINER(widget))
  197. {
  198. rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
  199. {
  200. child = rtgui_list_entry(node, rtgui_widget_t, sibling);
  201. _widget_move(child, dx, dy);
  202. }
  203. }
  204. }
  205. /*
  206. * This function moves widget and its children to a logic point
  207. */
  208. void rtgui_widget_move_to_logic(rtgui_widget_t *widget, int dx, int dy)
  209. {
  210. rtgui_rect_t rect;
  211. rtgui_widget_t *parent;
  212. if (widget == RT_NULL)
  213. return;
  214. /* give clip of this widget back to parent */
  215. parent = widget->parent;
  216. if (parent != RT_NULL)
  217. {
  218. /* get the parent rect, even if it's a transparent parent. */
  219. rect = parent->extent_visiable;
  220. }
  221. /* we should find out the none-transparent parent */
  222. while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
  223. if (parent != RT_NULL)
  224. {
  225. /* reset clip info */
  226. rtgui_region_init_with_extents(&(widget->clip), &(widget->extent));
  227. rtgui_region_intersect_rect(&(widget->clip), &(widget->clip), &rect);
  228. /* give back the extent */
  229. rtgui_region_union(&(parent->clip), &(parent->clip), &(widget->clip));
  230. }
  231. /* move this widget (and its children if it's a container) to destination point */
  232. _widget_move(widget, dx, dy);
  233. /* update this widget */
  234. rtgui_widget_update_clip(widget);
  235. }
  236. RTM_EXPORT(rtgui_widget_move_to_logic);
  237. void rtgui_widget_get_rect(rtgui_widget_t *widget, rtgui_rect_t *rect)
  238. {
  239. RT_ASSERT(widget != RT_NULL);
  240. if (rect != RT_NULL)
  241. {
  242. rect->x1 = rect->y1 = 0;
  243. rect->x2 = widget->extent.x2 - widget->extent.x1;
  244. rect->y2 = widget->extent.y2 - widget->extent.y1;
  245. }
  246. }
  247. RTM_EXPORT(rtgui_widget_get_rect);
  248. /**
  249. * set widget draw style
  250. */
  251. void rtgui_widget_set_border(rtgui_widget_t *widget, rt_uint32_t style)
  252. {
  253. RT_ASSERT(widget != RT_NULL);
  254. widget->border_style = style;
  255. switch (style)
  256. {
  257. case RTGUI_BORDER_NONE:
  258. widget->border = 0;
  259. break;
  260. case RTGUI_BORDER_SIMPLE:
  261. case RTGUI_BORDER_UP:
  262. case RTGUI_BORDER_DOWN:
  263. widget->border = 1;
  264. break;
  265. case RTGUI_BORDER_STATIC:
  266. case RTGUI_BORDER_RAISE:
  267. case RTGUI_BORDER_SUNKEN:
  268. case RTGUI_BORDER_BOX:
  269. case RTGUI_BORDER_EXTRA:
  270. widget->border = 2;
  271. break;
  272. default:
  273. widget->border = 2;
  274. break;
  275. }
  276. }
  277. RTM_EXPORT(rtgui_widget_set_border);
  278. void rtgui_widget_set_onfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
  279. {
  280. RT_ASSERT(widget != RT_NULL);
  281. widget->on_focus_in = handler;
  282. }
  283. RTM_EXPORT(rtgui_widget_set_onfocus);
  284. void rtgui_widget_set_onunfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
  285. {
  286. RT_ASSERT(widget != RT_NULL);
  287. widget->on_focus_out = handler;
  288. }
  289. RTM_EXPORT(rtgui_widget_set_onunfocus);
  290. /**
  291. * @brief Focuses the widget. The focused widget is the widget which can receive the keyboard events
  292. * @param widget a widget
  293. * @note The widget has to be attached to a toplevel widget, otherwise it will have no effect
  294. */
  295. void rtgui_widget_focus(rtgui_widget_t *widget)
  296. {
  297. struct rtgui_widget *old_focus;
  298. RT_ASSERT(widget != RT_NULL);
  299. RT_ASSERT(widget->toplevel != RT_NULL);
  300. if (!RTGUI_WIDGET_IS_FOCUSABLE(widget) || !RTGUI_WIDGET_IS_ENABLE(widget))
  301. return;
  302. old_focus = RTGUI_WIN(widget->toplevel)->focused_widget;
  303. if (old_focus == widget)
  304. return; /* it's the same focused widget */
  305. /* unfocused the old widget */
  306. if (old_focus != RT_NULL)
  307. rtgui_widget_unfocus(old_focus);
  308. /* set widget as focused */
  309. widget->flag |= RTGUI_WIDGET_FLAG_FOCUS;
  310. RTGUI_WIN(widget->toplevel)->focused_widget = widget;
  311. /* invoke on focus in call back */
  312. if (widget->on_focus_in != RT_NULL)
  313. widget->on_focus_in(RTGUI_OBJECT(widget), RT_NULL);
  314. }
  315. RTM_EXPORT(rtgui_widget_focus);
  316. /**
  317. * @brief Unfocused the widget
  318. * @param widget a widget
  319. */
  320. void rtgui_widget_unfocus(rtgui_widget_t *widget)
  321. {
  322. RT_ASSERT(widget != RT_NULL);
  323. if (!widget->toplevel || !RTGUI_WIDGET_IS_FOCUSED(widget))
  324. return;
  325. widget->flag &= ~RTGUI_WIDGET_FLAG_FOCUS;
  326. if (widget->on_focus_out != RT_NULL)
  327. widget->on_focus_out(RTGUI_OBJECT(widget), RT_NULL);
  328. RTGUI_WIN(widget->toplevel)->focused_widget = RT_NULL;
  329. /* Ergodic constituent widget, make child loss of focus */
  330. if (RTGUI_IS_CONTAINER(widget))
  331. {
  332. rtgui_list_t *node;
  333. rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
  334. {
  335. rtgui_widget_t *child = rtgui_list_entry(node, rtgui_widget_t, sibling);
  336. if (RTGUI_WIDGET_IS_HIDE(child)) continue;
  337. rtgui_widget_unfocus(child);
  338. }
  339. }
  340. }
  341. RTM_EXPORT(rtgui_widget_unfocus);
  342. void rtgui_widget_point_to_device(rtgui_widget_t *widget, rtgui_point_t *point)
  343. {
  344. RT_ASSERT(widget != RT_NULL);
  345. if (point != RT_NULL)
  346. {
  347. point->x += widget->extent.x1;
  348. point->y += widget->extent.y1;
  349. }
  350. }
  351. RTM_EXPORT(rtgui_widget_point_to_device);
  352. void rtgui_widget_rect_to_device(rtgui_widget_t *widget, rtgui_rect_t *rect)
  353. {
  354. RT_ASSERT(widget != RT_NULL);
  355. if (rect != RT_NULL)
  356. {
  357. rect->x1 += widget->extent.x1;
  358. rect->x2 += widget->extent.x1;
  359. rect->y1 += widget->extent.y1;
  360. rect->y2 += widget->extent.y1;
  361. }
  362. }
  363. RTM_EXPORT(rtgui_widget_rect_to_device);
  364. void rtgui_widget_point_to_logic(rtgui_widget_t *widget, rtgui_point_t *point)
  365. {
  366. RT_ASSERT(widget != RT_NULL);
  367. if (point != RT_NULL)
  368. {
  369. point->x -= widget->extent.x1;
  370. point->y -= widget->extent.y1;
  371. }
  372. }
  373. RTM_EXPORT(rtgui_widget_point_to_logic);
  374. void rtgui_widget_rect_to_logic(rtgui_widget_t *widget, rtgui_rect_t *rect)
  375. {
  376. RT_ASSERT(widget != RT_NULL);
  377. if (rect != RT_NULL)
  378. {
  379. rect->x1 -= widget->extent.x1;
  380. rect->x2 -= widget->extent.x1;
  381. rect->y1 -= widget->extent.y1;
  382. rect->y2 -= widget->extent.y1;
  383. }
  384. }
  385. RTM_EXPORT(rtgui_widget_rect_to_logic);
  386. struct rtgui_win *rtgui_widget_get_toplevel(rtgui_widget_t *widget)
  387. {
  388. rtgui_widget_t *r;
  389. RT_ASSERT(widget != RT_NULL);
  390. if (widget->toplevel)
  391. return widget->toplevel;
  392. rt_kprintf("widget->toplevel not properly set\n");
  393. r = widget;
  394. /* get the toplevel widget */
  395. while (r->parent != RT_NULL)
  396. r = r->parent;
  397. /* set toplevel */
  398. widget->toplevel = RTGUI_WIN(r);
  399. return RTGUI_WIN(r);
  400. }
  401. RTM_EXPORT(rtgui_widget_get_toplevel);
  402. rt_bool_t rtgui_widget_onupdate_toplvl(struct rtgui_object *object, struct rtgui_event *event)
  403. {
  404. struct rtgui_widget *widget;
  405. struct rtgui_event_update_toplvl *eup;
  406. RT_ASSERT(object);
  407. RT_ASSERT(event);
  408. widget = RTGUI_WIDGET(object);
  409. eup = (struct rtgui_event_update_toplvl *)event;
  410. widget->toplevel = eup->toplvl;
  411. return RT_FALSE;
  412. }
  413. RTM_EXPORT(rtgui_widget_onupdate_toplvl);
  414. rt_bool_t rtgui_widget_event_handler(struct rtgui_object *object, rtgui_event_t *event)
  415. {
  416. RTGUI_WIDGET_EVENT_HANDLER_PREPARE;
  417. switch (event->type)
  418. {
  419. case RTGUI_EVENT_PAINT:
  420. break;
  421. case RTGUI_EVENT_SHOW:
  422. return rtgui_widget_onshow(object, event);
  423. case RTGUI_EVENT_HIDE:
  424. return rtgui_widget_onhide(object, event);
  425. case RTGUI_EVENT_UPDATE_TOPLVL:
  426. return rtgui_widget_onupdate_toplvl(object, event);
  427. default:
  428. break;
  429. }
  430. return rtgui_object_event_handler(object, event);
  431. }
  432. RTM_EXPORT(rtgui_widget_event_handler);
  433. /*
  434. * This function updates the clip info of widget
  435. */
  436. void rtgui_widget_update_clip(rtgui_widget_t *widget)
  437. {
  438. rtgui_rect_t rect;
  439. struct rtgui_list_node *node;
  440. rtgui_widget_t *parent;
  441. /* no widget or widget is hide, no update clip */
  442. if (widget == RT_NULL || RTGUI_WIDGET_IS_HIDE(widget) || widget->parent == RT_NULL)
  443. return;
  444. parent = widget->parent;
  445. /* reset visiable extent */
  446. widget->extent_visiable = widget->extent;
  447. rtgui_rect_intersect(&(parent->extent_visiable), &(widget->extent_visiable));
  448. rect = parent->extent_visiable;
  449. /* reset clip to extent */
  450. rtgui_region_reset(&(widget->clip), &(widget->extent));
  451. /* limit widget extent in parent extent */
  452. rtgui_region_intersect_rect(&(widget->clip), &(widget->clip), &rect);
  453. /* get the no transparent parent */
  454. while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT)
  455. {
  456. parent = parent->parent;
  457. }
  458. if (parent != RT_NULL)
  459. {
  460. /* give my clip back to parent */
  461. rtgui_region_union(&(parent->clip), &(parent->clip), &(widget->clip));
  462. /* subtract widget clip in parent clip */
  463. if (!(widget->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) && RTGUI_IS_CONTAINER(parent))
  464. {
  465. rtgui_region_subtract_rect(&(parent->clip), &(parent->clip), &(widget->extent_visiable));
  466. }
  467. }
  468. /*
  469. * note: since the layout widget introduction, the sibling widget should not intersect.
  470. */
  471. /* if it's a container object, update the clip info of children */
  472. if (RTGUI_IS_CONTAINER(widget))
  473. {
  474. rtgui_widget_t *child;
  475. rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
  476. {
  477. child = rtgui_list_entry(node, rtgui_widget_t, sibling);
  478. rtgui_widget_update_clip(child);
  479. }
  480. }
  481. }
  482. RTM_EXPORT(rtgui_widget_update_clip);
  483. void rtgui_widget_show(struct rtgui_widget *widget)
  484. {
  485. struct rtgui_event_show eshow;
  486. RT_ASSERT(widget != RT_NULL);
  487. if (!RTGUI_WIDGET_IS_HIDE(widget))
  488. return;
  489. RTGUI_WIDGET_UNHIDE(widget);
  490. if (widget->toplevel != RT_NULL)
  491. {
  492. RTGUI_EVENT_SHOW_INIT(&eshow);
  493. if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
  494. {
  495. RTGUI_OBJECT(widget)->event_handler(
  496. RTGUI_OBJECT(widget),
  497. &eshow);
  498. }
  499. }
  500. }
  501. RTM_EXPORT(rtgui_widget_show);
  502. void rtgui_widget_hide(struct rtgui_widget *widget)
  503. {
  504. struct rtgui_event_hide ehide;
  505. RT_ASSERT(widget != RT_NULL);
  506. if (RTGUI_WIDGET_IS_HIDE(widget))
  507. return;
  508. if (widget->toplevel != RT_NULL)
  509. {
  510. RTGUI_EVENT_HIDE_INIT(&ehide);
  511. if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
  512. {
  513. RTGUI_OBJECT(widget)->event_handler(
  514. RTGUI_OBJECT(widget),
  515. &ehide);
  516. }
  517. }
  518. RTGUI_WIDGET_HIDE(widget);
  519. }
  520. RTM_EXPORT(rtgui_widget_hide);
  521. rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event)
  522. {
  523. struct rtgui_widget *widget = RTGUI_WIDGET(object);
  524. if (RTGUI_WIDGET_IS_HIDE(object)) return RT_FALSE;
  525. if (widget->parent != RT_NULL && !(RTGUI_WIDGET_FLAG(widget) & RTGUI_WIDGET_FLAG_TRANSPARENT))
  526. {
  527. rtgui_widget_clip_parent(widget);
  528. }
  529. return RT_FALSE;
  530. }
  531. RTM_EXPORT(rtgui_widget_onshow);
  532. rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *event)
  533. {
  534. struct rtgui_widget *widget = RTGUI_WIDGET(object);
  535. if (RTGUI_WIDGET_IS_HIDE(object))
  536. return RT_FALSE;
  537. if (widget->parent != RT_NULL)
  538. {
  539. rtgui_widget_clip_return(widget);
  540. }
  541. return RT_FALSE;
  542. }
  543. RTM_EXPORT(rtgui_widget_onhide);
  544. rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t *widget)
  545. {
  546. rtgui_widget_t *parent;
  547. /* get parent widget */
  548. parent = widget->parent;
  549. if (parent == RT_NULL)
  550. return RTGUI_WIDGET_FOREGROUND(widget);
  551. while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
  552. parent = parent->parent;
  553. /* get parent's color */
  554. return RTGUI_WIDGET_FOREGROUND(parent);
  555. }
  556. RTM_EXPORT(rtgui_widget_get_parent_foreground);
  557. rtgui_color_t rtgui_widget_get_parent_background(rtgui_widget_t *widget)
  558. {
  559. rtgui_widget_t *parent;
  560. /* get parent widget */
  561. parent = widget->parent;
  562. if (parent == RT_NULL)
  563. return RTGUI_WIDGET_BACKGROUND(widget);
  564. while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
  565. parent = parent->parent;
  566. /* get parent's color */
  567. return RTGUI_WIDGET_BACKGROUND(parent);
  568. }
  569. RTM_EXPORT(rtgui_widget_get_parent_background);
  570. void rtgui_widget_clip_parent(rtgui_widget_t *widget)
  571. {
  572. rtgui_widget_t *parent;
  573. parent = widget->parent;
  574. /* get the no transparent parent */
  575. while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
  576. /* clip the widget extern from parent */
  577. if (parent != RT_NULL) rtgui_region_subtract(&(parent->clip), &(parent->clip), &(widget->clip));
  578. }
  579. RTM_EXPORT(rtgui_widget_clip_parent);
  580. void rtgui_widget_clip_return(rtgui_widget_t *widget)
  581. {
  582. rtgui_widget_t *parent;
  583. parent = widget->parent;
  584. /* get the no transparent parent */
  585. while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
  586. /* give clip back to parent */
  587. if (parent != RT_NULL) rtgui_region_union(&(parent->clip), &(parent->clip), &(widget->clip));
  588. }
  589. RTM_EXPORT(rtgui_widget_clip_return);
  590. void rtgui_widget_update(rtgui_widget_t *widget)
  591. {
  592. struct rtgui_event_paint paint;
  593. RTGUI_EVENT_PAINT_INIT(&paint);
  594. paint.wid = RT_NULL;
  595. RT_ASSERT(widget != RT_NULL);
  596. if (RTGUI_OBJECT(widget)->event_handler != RT_NULL &&
  597. !(RTGUI_WIDGET_FLAG(widget) & RTGUI_WIDGET_FLAG_IN_ANIM))
  598. {
  599. RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
  600. &paint.parent);
  601. }
  602. }
  603. RTM_EXPORT(rtgui_widget_update);
  604. rtgui_widget_t *rtgui_widget_get_next_sibling(rtgui_widget_t *widget)
  605. {
  606. rtgui_widget_t *sibling = RT_NULL;
  607. if (widget->sibling.next != RT_NULL)
  608. {
  609. sibling = rtgui_list_entry(widget->sibling.next, rtgui_widget_t, sibling);
  610. }
  611. return sibling;
  612. }
  613. RTM_EXPORT(rtgui_widget_get_next_sibling);
  614. rtgui_widget_t *rtgui_widget_get_prev_sibling(rtgui_widget_t *widget)
  615. {
  616. struct rtgui_list_node *node;
  617. rtgui_widget_t *sibling, *parent;
  618. node = RT_NULL;
  619. sibling = RT_NULL;
  620. parent = widget->parent;
  621. if (parent != RT_NULL)
  622. {
  623. rtgui_list_foreach(node, &(RTGUI_CONTAINER(parent)->children))
  624. {
  625. if (node->next == &(widget->sibling))
  626. break;
  627. }
  628. }
  629. if (node != RT_NULL)
  630. sibling = rtgui_list_entry(node, rtgui_widget_t, sibling);
  631. return sibling;
  632. }
  633. RTM_EXPORT(rtgui_widget_get_prev_sibling);
  634. rt_bool_t rtgui_widget_is_in_animation(rtgui_widget_t *widget)
  635. {
  636. /* check the visible of widget */
  637. while (widget != RT_NULL)
  638. {
  639. if (widget->flag & RTGUI_WIDGET_FLAG_IN_ANIM)
  640. {
  641. return RT_TRUE;
  642. }
  643. widget = widget->parent;
  644. }
  645. return RT_FALSE;
  646. }
  647. RTM_EXPORT(rtgui_widget_is_in_animation);
  648. #ifdef RTGUI_WIDGET_DEBUG
  649. #include <rtgui/widgets/label.h>
  650. #include <rtgui/widgets/button.h>
  651. void rtgui_widget_dump(rtgui_widget_t *widget)
  652. {
  653. struct rtgui_object *obj;
  654. obj = RTGUI_OBJECT(widget);
  655. rt_kprintf("widget type: %s ", obj->type->name);
  656. if (RTGUI_IS_WIN(widget) == RT_TRUE)
  657. rt_kprintf(":%s ", RTGUI_WIN(widget)->title);
  658. else if ((RTGUI_IS_LABEL(widget) == RT_TRUE) || (RTGUI_IS_BUTTON(widget) == RT_TRUE))
  659. rt_kprintf(":%s ", RTGUI_LABEL(widget)->text);
  660. rt_kprintf("extent(%d, %d) - (%d, %d)\n", widget->extent.x1,
  661. widget->extent.y1, widget->extent.x2, widget->extent.y2);
  662. // rtgui_region_dump(&(widget->clip));
  663. }
  664. #endif