widget.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  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 || rtgui_widget_is_in_animation(widget))
  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_widget_update_clip(widget);
  493. RTGUI_EVENT_SHOW_INIT(&eshow);
  494. if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
  495. {
  496. RTGUI_OBJECT(widget)->event_handler(
  497. RTGUI_OBJECT(widget),
  498. &eshow);
  499. }
  500. }
  501. }
  502. RTM_EXPORT(rtgui_widget_show);
  503. void rtgui_widget_hide(struct rtgui_widget *widget)
  504. {
  505. struct rtgui_event_hide ehide;
  506. RT_ASSERT(widget != RT_NULL);
  507. if (RTGUI_WIDGET_IS_HIDE(widget))
  508. return;
  509. if (widget->toplevel != RT_NULL)
  510. {
  511. RTGUI_EVENT_HIDE_INIT(&ehide);
  512. if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
  513. {
  514. RTGUI_OBJECT(widget)->event_handler(
  515. RTGUI_OBJECT(widget),
  516. &ehide);
  517. }
  518. }
  519. RTGUI_WIDGET_HIDE(widget);
  520. }
  521. RTM_EXPORT(rtgui_widget_hide);
  522. rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event)
  523. {
  524. struct rtgui_widget *widget = RTGUI_WIDGET(object);
  525. if (RTGUI_WIDGET_IS_HIDE(object)) return RT_FALSE;
  526. if (widget->parent != RT_NULL && !(RTGUI_WIDGET_FLAG(widget) & RTGUI_WIDGET_FLAG_TRANSPARENT))
  527. {
  528. rtgui_widget_clip_parent(widget);
  529. }
  530. return RT_FALSE;
  531. }
  532. RTM_EXPORT(rtgui_widget_onshow);
  533. rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *event)
  534. {
  535. struct rtgui_widget *widget = RTGUI_WIDGET(object);
  536. if (RTGUI_WIDGET_IS_HIDE(object))
  537. return RT_FALSE;
  538. if (widget->parent != RT_NULL)
  539. {
  540. rtgui_widget_clip_return(widget);
  541. }
  542. return RT_FALSE;
  543. }
  544. RTM_EXPORT(rtgui_widget_onhide);
  545. rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t *widget)
  546. {
  547. rtgui_widget_t *parent;
  548. /* get parent widget */
  549. parent = widget->parent;
  550. if (parent == RT_NULL)
  551. return RTGUI_WIDGET_FOREGROUND(widget);
  552. while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
  553. parent = parent->parent;
  554. /* get parent's color */
  555. return RTGUI_WIDGET_FOREGROUND(parent);
  556. }
  557. RTM_EXPORT(rtgui_widget_get_parent_foreground);
  558. rtgui_color_t rtgui_widget_get_parent_background(rtgui_widget_t *widget)
  559. {
  560. rtgui_widget_t *parent;
  561. /* get parent widget */
  562. parent = widget->parent;
  563. if (parent == RT_NULL)
  564. return RTGUI_WIDGET_BACKGROUND(widget);
  565. while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
  566. parent = parent->parent;
  567. /* get parent's color */
  568. return RTGUI_WIDGET_BACKGROUND(parent);
  569. }
  570. RTM_EXPORT(rtgui_widget_get_parent_background);
  571. void rtgui_widget_clip_parent(rtgui_widget_t *widget)
  572. {
  573. rtgui_widget_t *parent;
  574. parent = widget->parent;
  575. /* get the no transparent parent */
  576. while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
  577. /* clip the widget extern from parent */
  578. if (parent != RT_NULL) rtgui_region_subtract(&(parent->clip), &(parent->clip), &(widget->clip));
  579. }
  580. RTM_EXPORT(rtgui_widget_clip_parent);
  581. void rtgui_widget_clip_return(rtgui_widget_t *widget)
  582. {
  583. rtgui_widget_t *parent;
  584. parent = widget->parent;
  585. /* get the no transparent parent */
  586. while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
  587. /* give clip back to parent */
  588. if (parent != RT_NULL) rtgui_region_union(&(parent->clip), &(parent->clip), &(widget->clip));
  589. }
  590. RTM_EXPORT(rtgui_widget_clip_return);
  591. void rtgui_widget_update(rtgui_widget_t *widget)
  592. {
  593. struct rtgui_event_paint paint;
  594. RTGUI_EVENT_PAINT_INIT(&paint);
  595. paint.wid = RT_NULL;
  596. RT_ASSERT(widget != RT_NULL);
  597. if (RTGUI_OBJECT(widget)->event_handler != RT_NULL &&
  598. !(RTGUI_WIDGET_FLAG(widget) & RTGUI_WIDGET_FLAG_IN_ANIM))
  599. {
  600. RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
  601. &paint.parent);
  602. }
  603. }
  604. RTM_EXPORT(rtgui_widget_update);
  605. rtgui_widget_t *rtgui_widget_get_next_sibling(rtgui_widget_t *widget)
  606. {
  607. rtgui_widget_t *sibling = RT_NULL;
  608. if (widget->sibling.next != RT_NULL)
  609. {
  610. sibling = rtgui_list_entry(widget->sibling.next, rtgui_widget_t, sibling);
  611. }
  612. return sibling;
  613. }
  614. RTM_EXPORT(rtgui_widget_get_next_sibling);
  615. rtgui_widget_t *rtgui_widget_get_prev_sibling(rtgui_widget_t *widget)
  616. {
  617. struct rtgui_list_node *node;
  618. rtgui_widget_t *sibling, *parent;
  619. node = RT_NULL;
  620. sibling = RT_NULL;
  621. parent = widget->parent;
  622. if (parent != RT_NULL)
  623. {
  624. rtgui_list_foreach(node, &(RTGUI_CONTAINER(parent)->children))
  625. {
  626. if (node->next == &(widget->sibling))
  627. break;
  628. }
  629. }
  630. if (node != RT_NULL)
  631. sibling = rtgui_list_entry(node, rtgui_widget_t, sibling);
  632. return sibling;
  633. }
  634. RTM_EXPORT(rtgui_widget_get_prev_sibling);
  635. rt_bool_t rtgui_widget_is_in_animation(rtgui_widget_t *widget)
  636. {
  637. /* check the visible of widget */
  638. while (widget != RT_NULL)
  639. {
  640. if (widget->flag & RTGUI_WIDGET_FLAG_IN_ANIM)
  641. {
  642. return RT_TRUE;
  643. }
  644. widget = widget->parent;
  645. }
  646. return RT_FALSE;
  647. }
  648. RTM_EXPORT(rtgui_widget_is_in_animation);
  649. #ifdef RTGUI_WIDGET_DEBUG
  650. #include <rtgui/widgets/label.h>
  651. #include <rtgui/widgets/button.h>
  652. void rtgui_widget_dump(rtgui_widget_t *widget)
  653. {
  654. struct rtgui_object *obj;
  655. obj = RTGUI_OBJECT(widget);
  656. rt_kprintf("widget type: %s ", obj->type->name);
  657. if (RTGUI_IS_WIN(widget) == RT_TRUE)
  658. rt_kprintf(":%s ", RTGUI_WIN(widget)->title);
  659. else if ((RTGUI_IS_LABEL(widget) == RT_TRUE) || (RTGUI_IS_BUTTON(widget) == RT_TRUE))
  660. rt_kprintf(":%s ", RTGUI_LABEL(widget)->text);
  661. rt_kprintf("extent(%d, %d) - (%d, %d)\n", widget->extent.x1,
  662. widget->extent.y1, widget->extent.x2, widget->extent.y2);
  663. // rtgui_region_dump(&(widget->clip));
  664. }
  665. #endif