/src/ftk_dialog.c

http://ftk.googlecode.com/ · C · 393 lines · 286 code · 78 blank · 29 comment · 56 complexity · 1ce621ec12f6d9913c4d4aca0a2a7f97 MD5 · raw file

  1. /*
  2. * File: ftk_dialog.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: dialog
  5. *
  6. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2009-10-15 Li XianJing <xianjimli@hotmail.com> created
  28. * 2012-5-3 woodysu@gmail.com modified
  29. */
  30. #include "ftk_dialog.h"
  31. #include "ftk_globals.h"
  32. #include "ftk_main_loop.h"
  33. #include "ftk_source_timer.h"
  34. typedef struct _DialogPrivInfo
  35. {
  36. int no_title;
  37. int title_height;
  38. FtkBitmap* icon;
  39. FtkBitmap* bg;
  40. FtkBitmap* title_bg;
  41. FtkSource* timer;
  42. FtkMainLoop* main_loop;
  43. FtkWidgetOnEvent parent_on_event;
  44. FtkWidgetOnPaint parent_on_paint;
  45. FtkWidgetDestroy parent_destroy;
  46. }PrivInfo;
  47. static int ftk_dialog_is_modal(FtkWidget* thiz)
  48. {
  49. DECL_PRIV1(thiz, priv);
  50. return priv != NULL && priv->main_loop != NULL;
  51. }
  52. Ret ftk_dialog_set_icon(FtkWidget* thiz, FtkBitmap* icon)
  53. {
  54. DECL_PRIV1(thiz, priv);
  55. return_val_if_fail(thiz != NULL, RET_FAIL);
  56. if(priv->icon != NULL)
  57. {
  58. ftk_bitmap_unref(priv->icon);
  59. }
  60. priv->icon = icon;
  61. if(priv->icon != NULL)
  62. {
  63. ftk_bitmap_ref(priv->icon);
  64. }
  65. return RET_OK;
  66. }
  67. Ret ftk_dialog_hide_title(FtkWidget* thiz)
  68. {
  69. DECL_PRIV1(thiz, priv);
  70. return_val_if_fail(thiz != NULL, RET_FAIL);
  71. priv->no_title = 1;
  72. return RET_OK;
  73. }
  74. static Ret ftk_dialog_on_event(FtkWidget* thiz, FtkEvent* event)
  75. {
  76. DECL_PRIV1(thiz, priv);
  77. Ret ret = priv->parent_on_event(thiz, event);
  78. if(ret == RET_QUIT && ftk_dialog_is_modal(thiz))
  79. {
  80. ftk_main_loop_quit(priv->main_loop);
  81. }
  82. switch(event->type)
  83. {
  84. case FTK_EVT_ADD_CHILD:
  85. {
  86. int x = 0;
  87. int y = 0;
  88. FtkWidget* child = (FtkWidget*)event->u.extra;
  89. x = ftk_widget_left(child) + FTK_DIALOG_BORDER;
  90. y = ftk_widget_top(child) + (priv->no_title ? FTK_DIALOG_BORDER : priv->title_height);
  91. ftk_widget_move(child, x, y);
  92. break;
  93. }
  94. case FTK_EVT_MOUSE_UP:
  95. {
  96. int p_x = event->u.mouse.x;
  97. int p_y = event->u.mouse.y;
  98. int x = ftk_widget_left_abs(thiz);
  99. int y = ftk_widget_top_abs(thiz);
  100. int w = ftk_widget_width(thiz);
  101. int h = ftk_widget_height(thiz);
  102. if(p_x < x || p_y < y || (p_x > (x + w)) || (p_y > (y + h)))
  103. {
  104. if(thiz->ref > 1 && ftk_widget_has_attr(thiz, FTK_ATTR_POPUP))
  105. {
  106. if(ftk_dialog_is_modal(thiz))
  107. {
  108. ftk_dialog_quit(thiz);
  109. }
  110. else
  111. {
  112. ftk_widget_unref(thiz);
  113. }
  114. }
  115. }
  116. break;
  117. }
  118. default:break;
  119. }
  120. return RET_OK;
  121. }
  122. static Ret ftk_dialog_clear_alpha(FtkCanvas* canvas, int x, int y)
  123. {
  124. return RET_OK;
  125. }
  126. static Ret ftk_dialog_change_alpha(FtkWidget* thiz, FtkCanvas* canvas, int x, int y, int width, int height)
  127. {
  128. ftk_dialog_clear_alpha(canvas, x, y);
  129. ftk_dialog_clear_alpha(canvas, x+1, y);
  130. ftk_dialog_clear_alpha(canvas, x, y+1);
  131. ftk_dialog_clear_alpha(canvas, x+width-1, y) ;
  132. ftk_dialog_clear_alpha(canvas, x+width-2, y) ;
  133. ftk_dialog_clear_alpha(canvas, x+width-1, y+1);
  134. ftk_dialog_clear_alpha(canvas, x, y+height-1) ;
  135. ftk_dialog_clear_alpha(canvas, x+1, y+height-1);
  136. ftk_dialog_clear_alpha(canvas, x, y+height-2) ;
  137. ftk_dialog_clear_alpha(canvas, x+width-1, y+height-1);
  138. ftk_dialog_clear_alpha(canvas, x+width-2, y+height-1);
  139. ftk_dialog_clear_alpha(canvas, x+width-1, y+height-2);
  140. return RET_OK;
  141. }
  142. static Ret ftk_dialog_paint_border(FtkWidget* thiz, FtkCanvas* canvas, int x, int y, int width, int height)
  143. {
  144. DECL_PRIV1(thiz, priv);
  145. return_val_if_fail(priv->bg != NULL && priv->title_bg != NULL, RET_FAIL);
  146. if(!ftk_window_is_opaque(thiz))
  147. {
  148. return RET_OK;
  149. }
  150. if(priv->no_title)
  151. {
  152. ftk_canvas_draw_bg_image(canvas, priv->bg, FTK_BG_FOUR_CORNER, x, y, width, height);
  153. }
  154. else
  155. {
  156. int title_height = ftk_bitmap_height(priv->title_bg);
  157. return_val_if_fail(title_height < height, RET_FAIL);
  158. ftk_canvas_draw_bg_image(canvas, priv->title_bg, FTK_BG_TILE, x, y, width, title_height);
  159. ftk_canvas_draw_bg_image(canvas, priv->bg, FTK_BG_FOUR_CORNER, x, y+title_height, width, height-title_height);
  160. }
  161. return RET_OK;
  162. }
  163. static Ret ftk_dialog_paint_title(FtkWidget* thiz, FtkCanvas* canvas, int x, int y, int width, int height)
  164. {
  165. DECL_PRIV1(thiz, priv);
  166. if(priv->no_title) return RET_OK;
  167. if(priv->icon != NULL)
  168. {
  169. ftk_canvas_draw_bg_image(canvas, priv->icon, FTK_BG_CENTER, x + FTK_DIALOG_BORDER, y,
  170. priv->title_height, priv->title_height);
  171. }
  172. ftk_canvas_set_gc(canvas, ftk_widget_get_gc(thiz));
  173. if(ftk_widget_get_text(thiz) != NULL)
  174. {
  175. int xoffset = FTK_DIALOG_BORDER + (priv->icon != NULL ? priv->title_height : FTK_DIALOG_BORDER);
  176. int yoffset = priv->title_height >> 1;
  177. const char* text = ftk_widget_get_text(thiz);
  178. const char* end = ftk_canvas_calc_str_visible_range(canvas, text, 0, -1,
  179. width - xoffset - FTK_DIALOG_BORDER, NULL);
  180. ftk_canvas_draw_string(canvas, x + xoffset, y + yoffset, text, end - text, 1);
  181. }
  182. return RET_OK;
  183. }
  184. static Ret ftk_dialog_on_paint(FtkWidget* thiz)
  185. {
  186. DECL_PRIV1(thiz, priv);
  187. FTK_BEGIN_PAINT(x, y, width, height, canvas);
  188. return_val_if_fail(ftk_widget_is_visible(thiz), RET_FAIL);
  189. ftk_dialog_paint_border(thiz, canvas, x, y, width, height);
  190. ftk_dialog_paint_title(thiz, canvas, x, y, width, height);
  191. ftk_dialog_change_alpha(thiz, canvas, x, y, width, height);
  192. priv->parent_on_paint(thiz);
  193. return RET_OK;
  194. }
  195. static void ftk_dialog_destroy(FtkWidget* thiz)
  196. {
  197. DECL_PRIV1(thiz, priv);
  198. if(priv->parent_destroy != NULL)
  199. {
  200. priv->parent_destroy(thiz);
  201. }
  202. if(priv->icon != NULL)
  203. {
  204. ftk_bitmap_unref(priv->icon);
  205. }
  206. if(priv->bg != NULL)
  207. {
  208. ftk_bitmap_unref(priv->bg);
  209. }
  210. if(priv->title_bg != NULL)
  211. {
  212. ftk_bitmap_unref(priv->title_bg);
  213. }
  214. if(priv->timer != NULL)
  215. {
  216. ftk_main_loop_remove_source(ftk_default_main_loop(), priv->timer);
  217. }
  218. FTK_ZFREE(thiz->priv_subclass[1], sizeof(PrivInfo));
  219. return;
  220. }
  221. FtkWidget* ftk_dialog_create_ex(int attr, int x, int y, int width, int height)
  222. {
  223. FtkWidget* thiz = ftk_window_create(FTK_DIALOG, attr, x, y, width, height);
  224. return_val_if_fail(thiz != NULL, NULL);
  225. thiz->priv_subclass[1] = (PrivInfo*)FTK_ZALLOC(sizeof(PrivInfo));
  226. if(thiz->priv_subclass[1] != NULL)
  227. {
  228. DECL_PRIV1(thiz, priv);
  229. priv->parent_on_event = thiz->on_event;
  230. priv->parent_on_paint = thiz->on_paint;
  231. priv->parent_destroy = thiz->destroy;
  232. thiz->on_event = ftk_dialog_on_event;
  233. thiz->on_paint = ftk_dialog_on_paint;
  234. thiz->destroy = ftk_dialog_destroy;
  235. priv->bg = ftk_theme_load_image(ftk_default_theme(), "dialog_bg"FTK_STOCK_IMG_SUFFIX);
  236. priv->title_bg = ftk_theme_load_image(ftk_default_theme(), "dialog_title_bg"FTK_STOCK_IMG_SUFFIX);
  237. priv->title_height = ftk_bitmap_height(priv->title_bg);
  238. }
  239. else
  240. {
  241. ftk_widget_destroy(thiz);
  242. thiz = NULL;
  243. }
  244. return thiz;
  245. }
  246. Ret ftk_dialog_set_bg(FtkWidget* thiz, FtkBitmap* bitmap)
  247. {
  248. DECL_PRIV1(thiz, priv);
  249. return_val_if_fail(priv != NULL, RET_FAIL);
  250. ftk_bitmap_unref(priv->bg);
  251. priv->bg = bitmap;
  252. ftk_bitmap_ref(priv->bg);
  253. return RET_OK;
  254. }
  255. FtkWidget* ftk_dialog_create(int x, int y, int width, int height)
  256. {
  257. return ftk_dialog_create_ex(FTK_ATTR_AUTO_LAYOUT, x, y, width, height);
  258. }
  259. Ret ftk_dialog_quit(FtkWidget* thiz)
  260. {
  261. DECL_PRIV1(thiz, priv);
  262. return_val_if_fail(ftk_dialog_is_modal(thiz), RET_FAIL);
  263. ftk_main_loop_quit(priv->main_loop);
  264. return RET_OK;
  265. }
  266. static Ret ftk_dialog_timeout_quit(void* ctx)
  267. {
  268. FtkWidget* thiz = (FtkWidget*)ctx;
  269. DECL_PRIV1(thiz, priv);
  270. return_val_if_fail(priv != NULL && priv->timer != NULL, RET_REMOVE);
  271. priv->timer = NULL;
  272. if(ftk_dialog_is_modal(thiz))
  273. {
  274. ftk_dialog_quit(thiz);
  275. }
  276. else
  277. {
  278. ftk_widget_unref(thiz);
  279. }
  280. return RET_REMOVE;
  281. }
  282. Ret ftk_dialog_quit_after(FtkWidget* thiz, int ms)
  283. {
  284. DECL_PRIV1(thiz, priv);
  285. return_val_if_fail(priv != NULL && priv->timer == NULL, RET_FAIL);
  286. priv->timer = ftk_source_timer_create(ms, ftk_dialog_timeout_quit, thiz);
  287. ftk_main_loop_add_source(ftk_default_main_loop(), priv->timer);
  288. return RET_OK;
  289. }
  290. int ftk_dialog_run(FtkWidget* thiz)
  291. {
  292. FtkMainLoop* prev_main_loop = ftk_default_main_loop();
  293. DECL_PRIV1(thiz, priv);
  294. return_val_if_fail(thiz != NULL, RET_FAIL);
  295. return_val_if_fail(ftk_widget_type(thiz) == FTK_DIALOG, RET_FAIL);
  296. priv->main_loop = ftk_main_loop_create(ftk_default_sources_manager());
  297. ftk_set_main_loop(priv->main_loop);
  298. ftk_widget_show_all(thiz, 1);
  299. ftk_main_loop_run(priv->main_loop);
  300. ftk_set_main_loop(prev_main_loop);
  301. ftk_main_loop_destroy(priv->main_loop);
  302. priv->main_loop = NULL;
  303. return ftk_widget_id(ftk_window_get_focus(thiz));
  304. }
  305. int ftk_dialog_get_title_height(void)
  306. {
  307. static int title_height = 0;
  308. if(title_height == 0)
  309. {
  310. FtkBitmap* title_bg = ftk_theme_load_image(ftk_default_theme(), "dialog_title_bg"FTK_STOCK_IMG_SUFFIX);
  311. title_height = ftk_bitmap_height(title_bg);
  312. ftk_bitmap_unref(title_bg);
  313. }
  314. return title_height;
  315. }