/src/ftk_xul.c

http://ftk.googlecode.com/ · C · 1147 lines · 908 code · 187 blank · 52 comment · 204 complexity · 32ecbe2cb9c0b92eacba6f3a65311c9b MD5 · raw file

  1. /*
  2. * File: ftk_xul.h
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: create ui from xml.
  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-11-23 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include "ftk.h"
  31. #include "ftk_xul.h"
  32. #include "ftk_expr.h"
  33. #include "ftk_util.h"
  34. #include "ftk_mmap.h"
  35. #include "ftk_xml_parser.h"
  36. typedef struct _XulPrivInfo
  37. {
  38. FtkWidget* root;
  39. FtkWidget* current;
  40. int meet_start_tag;
  41. int prev_is_widget;
  42. char processed_value[128];
  43. char translated_path[FTK_MAX_PATH+1];
  44. FtkXulCallbacks* callbacks;
  45. }PrivInfo;
  46. typedef struct _FtkWidgetCreateInfo
  47. {
  48. int id;
  49. int x;
  50. int y;
  51. int w;
  52. int h;
  53. int attr;
  54. int visible;
  55. char anim_hint[32];
  56. const char* value;
  57. FtkWidget* parent;
  58. FtkGc gc[FTK_WIDGET_STATE_NR];
  59. /*check button*/
  60. int checked;
  61. int icon_position;
  62. /* dialog */
  63. int hide_title;
  64. /* entry */
  65. const char *tips;
  66. /* file_browser */
  67. const char *filter;
  68. /* label */
  69. int alignment;
  70. /*scroll bar*/
  71. int max_value;
  72. int page_delta;
  73. /*text_view*/
  74. int readonly;
  75. int type;
  76. FtkBitmap* icon;
  77. const char *font;
  78. PrivInfo* priv;
  79. }FtkWidgetCreateInfo;
  80. typedef FtkWidget* (*FtkXulWidgetCreate)(FtkWidgetCreateInfo* info);
  81. typedef struct _WidgetCreator
  82. {
  83. const char* name;
  84. FtkXulWidgetCreate create;
  85. int is_widget;
  86. }WidgetCreator;
  87. static inline const char* ftk_xul_translate_text(FtkXulCallbacks* thiz, const char* text)
  88. {
  89. if(thiz == NULL || thiz->translate_text == NULL)
  90. {
  91. return text;
  92. }
  93. else
  94. {
  95. return thiz->translate_text(thiz->ctx, text);
  96. }
  97. }
  98. static inline FtkBitmap* ftk_xul_load_image(FtkXulCallbacks* thiz, const char* filename)
  99. {
  100. return_val_if_fail(thiz != NULL && thiz->load_image != NULL, NULL);
  101. return thiz->load_image(thiz->ctx, filename);
  102. }
  103. static FtkWidget* ftk_xul_label_create(FtkWidgetCreateInfo* info)
  104. {
  105. FtkWidget* widget = NULL;
  106. widget = ftk_label_create(info->parent, info->x, info->y, info->w, info->h);
  107. if(info->value != NULL)
  108. {
  109. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  110. }
  111. if(info->alignment > 0)
  112. {
  113. ftk_label_set_alignment(widget, info->alignment);
  114. }
  115. return widget;
  116. }
  117. static FtkWidget* ftk_xul_button_create(FtkWidgetCreateInfo* info)
  118. {
  119. FtkWidget* widget = NULL;
  120. widget = ftk_button_create(info->parent, info->x, info->y, info->w, info->h);
  121. if(info->value != NULL)
  122. {
  123. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  124. }
  125. return widget;
  126. }
  127. static FtkWidget* ftk_xul_entry_create(FtkWidgetCreateInfo* info)
  128. {
  129. FtkWidget* widget = NULL;
  130. widget = ftk_entry_create(info->parent, info->x, info->y, info->w, info->h);
  131. if(info->value != NULL)
  132. {
  133. ftk_entry_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  134. }
  135. if(info->tips != NULL)
  136. {
  137. ftk_entry_set_tips(widget, ftk_xul_translate_text(info->priv->callbacks, info->tips));
  138. }
  139. if(info->type > 0)
  140. {
  141. ftk_entry_set_input_type(widget, info->type);
  142. }
  143. return widget;
  144. }
  145. static FtkWidget* ftk_xul_wait_box_create(FtkWidgetCreateInfo* info)
  146. {
  147. FtkWidget* widget = NULL;
  148. widget = ftk_wait_box_create(info->parent, info->x, info->y, 0, 0);
  149. if(info->value != NULL && atoi(info->value) > 0)
  150. {
  151. ftk_wait_box_start_waiting(widget);
  152. }
  153. return widget;
  154. }
  155. static FtkWidget* ftk_xul_progress_bar_create(FtkWidgetCreateInfo* info)
  156. {
  157. FtkWidget* widget = NULL;
  158. int value = 0;
  159. widget = ftk_progress_bar_create(info->parent, info->x, info->y, info->w, info->h);
  160. if(info->value != NULL && (value = atoi(info->value)) > 0)
  161. {
  162. ftk_progress_bar_set_percent(widget, value);
  163. }
  164. if(info->tips != NULL)
  165. {
  166. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->tips));
  167. }
  168. return widget;
  169. }
  170. static FtkWidget* ftk_xul_group_box_create(FtkWidgetCreateInfo* info)
  171. {
  172. FtkWidget* widget = NULL;
  173. widget = ftk_group_box_create(info->parent, info->x, info->y, info->w, info->h);
  174. if(info->value != NULL)
  175. {
  176. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  177. }
  178. return widget;
  179. }
  180. static FtkWidget* ftk_xul_radio_button_create(FtkWidgetCreateInfo* info)
  181. {
  182. FtkWidget* widget = NULL;
  183. widget = ftk_check_button_create_radio(info->parent, info->x, info->y, info->w, info->h);
  184. if(info->value != NULL)
  185. {
  186. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  187. }
  188. if(info->icon_position > 0)
  189. {
  190. ftk_check_button_set_icon_position(widget, info->icon_position);
  191. }
  192. if(info->checked)
  193. {
  194. ftk_check_button_set_checked(widget, info->checked);
  195. }
  196. return widget;
  197. }
  198. static FtkWidget* ftk_xul_check_button_create(FtkWidgetCreateInfo* info)
  199. {
  200. FtkWidget* widget = NULL;
  201. widget = ftk_check_button_create(info->parent, info->x, info->y, info->w, info->h);
  202. if(info->value != NULL)
  203. {
  204. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  205. }
  206. if(info->icon_position > 0)
  207. {
  208. ftk_check_button_set_icon_position(widget, info->icon_position);
  209. }
  210. if(info->checked)
  211. {
  212. ftk_check_button_set_checked(widget, info->checked);
  213. }
  214. return widget;
  215. }
  216. static FtkWidget* ftk_xul_image_create(FtkWidgetCreateInfo* info)
  217. {
  218. FtkWidget* widget = NULL;
  219. widget = ftk_image_create(info->parent, info->x, info->y, info->w, info->h);
  220. if(info->value != NULL)
  221. {
  222. ftk_image_set_image(widget, ftk_xul_load_image(info->priv->callbacks, info->value));
  223. }
  224. return widget;
  225. }
  226. static FtkWidget* ftk_xul_scroll_bar_create(FtkWidgetCreateInfo* info)
  227. {
  228. FtkWidget* widget = NULL;
  229. int value = 0;
  230. widget = ftk_scroll_bar_create(info->parent, info->x, info->y, info->w, info->h);
  231. if(info->value != NULL && (value = atoi(info->value)) > 0)
  232. {
  233. ftk_scroll_bar_set_param(widget, value, info->max_value, info->page_delta);
  234. }
  235. return widget;
  236. }
  237. static FtkWidget* ftk_xul_list_view_create(FtkWidgetCreateInfo* info)
  238. {
  239. FtkWidget* widget = NULL;
  240. widget = ftk_list_view_create(info->parent, info->x, info->y, info->w, info->h);
  241. return widget;
  242. }
  243. static FtkWidget* ftk_xul_icon_view_create(FtkWidgetCreateInfo* info)
  244. {
  245. FtkWidget* widget = NULL;
  246. int value = 0;
  247. widget = ftk_icon_view_create(info->parent, info->x, info->y, info->w, info->h);
  248. if(info->value != NULL && (value = atoi(info->value)) > 0)
  249. {
  250. ftk_icon_view_set_item_size(widget, value);
  251. }
  252. return widget;
  253. }
  254. static FtkWidget* ftk_xul_icon_view_item_create(FtkWidgetCreateInfo* info)
  255. {
  256. DECL_PRIV(info, priv);
  257. FtkIconViewItem item;
  258. item.text = (char *)info->value;
  259. item.icon = info->icon;
  260. item.user_data = NULL;
  261. ftk_icon_view_add(priv->current, &item);
  262. return NULL;
  263. }
  264. static FtkWidget* ftk_xul_window_create(FtkWidgetCreateInfo* info)
  265. {
  266. FtkWidget* widget = NULL;
  267. widget = ftk_app_window_create();
  268. if(info->value != NULL)
  269. {
  270. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  271. }
  272. return widget;
  273. }
  274. static FtkWidget* ftk_xul_dialog_create(FtkWidgetCreateInfo* info)
  275. {
  276. FtkWidget* widget = NULL;
  277. widget = ftk_dialog_create(info->x, info->y, info->w, info->h);
  278. if(info->value != NULL)
  279. {
  280. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  281. }
  282. if(info->hide_title)
  283. {
  284. ftk_dialog_hide_title(widget);
  285. }
  286. if(info->icon != NULL)
  287. {
  288. ftk_dialog_set_icon(widget, info->icon);
  289. }
  290. return widget;
  291. }
  292. static FtkWidget* ftk_xul_combo_box_create(FtkWidgetCreateInfo* info)
  293. {
  294. FtkWidget* widget = NULL;
  295. widget = ftk_combo_box_create(info->parent, info->x, info->y, info->w, info->h);
  296. if(info->value != NULL)
  297. {
  298. ftk_combo_box_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  299. }
  300. return widget;
  301. }
  302. static FtkWidget* ftk_xul_combo_box_item_create(FtkWidgetCreateInfo* info)
  303. {
  304. DECL_PRIV(info, priv);
  305. ftk_combo_box_append(priv->current, info->icon, info->value);
  306. return NULL;
  307. }
  308. static FtkWidget* ftk_xul_file_browser_create(FtkWidgetCreateInfo* info)
  309. {
  310. FtkWidget* widget = NULL;
  311. widget = ftk_file_browser_create(info->type);
  312. if(info->value != NULL)
  313. {
  314. ftk_file_browser_set_path(widget, info->value);
  315. }
  316. if(info->filter != NULL)
  317. {
  318. ftk_file_browser_set_filter(widget, info->filter);
  319. }
  320. return widget;
  321. }
  322. static FtkWidget* ftk_xul_menu_panel_create(FtkWidgetCreateInfo* info)
  323. {
  324. FtkWidget* widget = NULL;
  325. widget = ftk_menu_panel_create();
  326. return widget;
  327. }
  328. static FtkWidget* ftk_xul_menu_item_create(FtkWidgetCreateInfo* info)
  329. {
  330. DECL_PRIV(info, priv);
  331. FtkWidget* widget = NULL;
  332. widget = ftk_menu_item_create(info->parent);
  333. if(info->value != NULL)
  334. {
  335. ftk_widget_set_text(widget, ftk_xul_translate_text(priv->callbacks, info->value));
  336. }
  337. ftk_menu_panel_relayout(info->parent);
  338. return widget;
  339. }
  340. static FtkWidget* ftk_xul_painter_create(FtkWidgetCreateInfo* info)
  341. {
  342. FtkWidget* widget = NULL;
  343. widget = ftk_painter_create(info->parent, info->x, info->y, info->w, info->h);
  344. return widget;
  345. }
  346. static FtkWidget* ftk_xul_status_item_create(FtkWidgetCreateInfo* info)
  347. {
  348. FtkWidget* widget = NULL;
  349. widget = ftk_status_item_create(ftk_default_status_panel(), info->x, info->w);
  350. if(info->value != NULL)
  351. {
  352. ftk_widget_set_text(widget, ftk_xul_translate_text(info->priv->callbacks, info->value));
  353. }
  354. return widget;
  355. }
  356. static FtkWidget* ftk_xul_tab_create(FtkWidgetCreateInfo* info)
  357. {
  358. FtkWidget* widget = NULL;
  359. widget = ftk_tab_create(info->parent, info->x, info->y, info->w, info->h);
  360. return widget;
  361. }
  362. static FtkWidget* ftk_xul_page_create(FtkWidgetCreateInfo* info)
  363. {
  364. FtkWidget* widget = NULL;
  365. widget = ftk_tab_add_page(info->parent, info->value, info->icon);
  366. return widget;
  367. }
  368. static FtkWidget* ftk_xul_text_view_create(FtkWidgetCreateInfo* info)
  369. {
  370. FtkWidget* widget = NULL;
  371. widget = ftk_text_view_create(info->parent, info->x, info->y, info->w, info->h);
  372. if(info->value != NULL)
  373. {
  374. const char *text = ftk_xul_translate_text(info->priv->callbacks, info->value);
  375. ftk_text_view_set_text(widget, text, strlen(text));
  376. }
  377. if(info->readonly)
  378. {
  379. ftk_text_view_set_readonly(widget, info->readonly);
  380. }
  381. return widget;
  382. }
  383. static const WidgetCreator s_widget_creaters[] =
  384. {
  385. {"label", ftk_xul_label_create, 1},
  386. {"entry", ftk_xul_entry_create, 1},
  387. {"button", ftk_xul_button_create, 1},
  388. {"wait_box", ftk_xul_wait_box_create, 1},
  389. {"progress_bar", ftk_xul_progress_bar_create, 1},
  390. {"group_box", ftk_xul_group_box_create, 1},
  391. {"radio_button", ftk_xul_radio_button_create, 1},
  392. {"check_button", ftk_xul_check_button_create, 1},
  393. {"image", ftk_xul_image_create, 1},
  394. {"scroll_bar", ftk_xul_scroll_bar_create, 1},
  395. {"list_view", ftk_xul_list_view_create, 1},
  396. {"icon_view", ftk_xul_icon_view_create, 1},
  397. {"icon_view_item", ftk_xul_icon_view_item_create, 0},
  398. {"window", ftk_xul_window_create, 1},
  399. {"dialog", ftk_xul_dialog_create, 1},
  400. {"combo_box", ftk_xul_combo_box_create, 1},
  401. {"combo_box_item", ftk_xul_combo_box_item_create, 0},
  402. {"file_browser", ftk_xul_file_browser_create, 1},
  403. {"menu_panel", ftk_xul_menu_panel_create, 1},
  404. {"menu_item", ftk_xul_menu_item_create, 1},
  405. {"painter", ftk_xul_painter_create, 1},
  406. {"status_item", ftk_xul_status_item_create, 1},
  407. {"tab", ftk_xul_tab_create, 1},
  408. {"page", ftk_xul_page_create, 1},
  409. {"text_view", ftk_xul_text_view_create, 1},
  410. {NULL, NULL},
  411. };
  412. static const WidgetCreator *ftk_xul_find_creator(const char* name)
  413. {
  414. int i = 0;
  415. return_val_if_fail(name != NULL, NULL);
  416. for(i = 0; s_widget_creaters[i].name != NULL; i++)
  417. {
  418. if(strcmp(s_widget_creaters[i].name, name) == 0)
  419. {
  420. return &s_widget_creaters[i];
  421. }
  422. }
  423. return NULL;
  424. }
  425. typedef int (*FtkXulVarGetter)(FtkXmlBuilder* thiz);
  426. typedef struct _VarGetter
  427. {
  428. const char* name;
  429. FtkXulVarGetter get;
  430. }VarGetter;
  431. static int ftk_xul_builder_get_parent_width(FtkXmlBuilder* thiz)
  432. {
  433. DECL_PRIV(thiz, priv);
  434. return ftk_widget_width(priv->current);
  435. }
  436. static int ftk_xul_builder_get_parent_height(FtkXmlBuilder* thiz)
  437. {
  438. DECL_PRIV(thiz, priv);
  439. return ftk_widget_height(priv->current);
  440. }
  441. static int ftk_xul_builder_get_window_width(FtkXmlBuilder* thiz)
  442. {
  443. DECL_PRIV(thiz, priv);
  444. return ftk_widget_width(priv->root);
  445. }
  446. static int ftk_xul_builder_get_window_height(FtkXmlBuilder* thiz)
  447. {
  448. DECL_PRIV(thiz, priv);
  449. return ftk_widget_height(priv->root);
  450. }
  451. static int ftk_xul_builder_get_display_width(FtkXmlBuilder* thiz)
  452. {
  453. return ftk_display_width(ftk_default_display());
  454. }
  455. static int ftk_xul_builder_get_display_height(FtkXmlBuilder* thiz)
  456. {
  457. return ftk_display_height(ftk_default_display());
  458. }
  459. static const VarGetter s_var_getters[] =
  460. {
  461. {"pw", ftk_xul_builder_get_parent_width},
  462. {"parent_width", ftk_xul_builder_get_parent_width},
  463. {"ph", ftk_xul_builder_get_parent_height},
  464. {"parent_height", ftk_xul_builder_get_parent_height},
  465. {"ww", ftk_xul_builder_get_window_width},
  466. {"window_width", ftk_xul_builder_get_window_width},
  467. {"wh", ftk_xul_builder_get_window_height},
  468. {"window_height", ftk_xul_builder_get_window_height},
  469. {"dw", ftk_xul_builder_get_display_width},
  470. {"display_width", ftk_xul_builder_get_display_width},
  471. {"dh", ftk_xul_builder_get_display_height},
  472. {"display_height", ftk_xul_builder_get_display_height},
  473. {NULL, NULL}
  474. };
  475. static int ftk_xul_find_getter(const char* name)
  476. {
  477. int i = 0;
  478. return_val_if_fail(name != NULL, 0);
  479. for(i = 0; s_var_getters[i].name != NULL; i++)
  480. {
  481. if(strncmp(s_var_getters[i].name, name, strlen(s_var_getters[i].name)) == 0)
  482. {
  483. return i;
  484. }
  485. }
  486. return -1;
  487. }
  488. typedef struct _VarConst
  489. {
  490. const char* name;
  491. int value;
  492. }VarConst;
  493. static const VarConst s_var_conts[] =
  494. {
  495. {"FTK_ATTR_TRANSPARENT", FTK_ATTR_TRANSPARENT},
  496. {"FTK_ATTR_IGNORE_CLOSE", FTK_ATTR_IGNORE_CLOSE},
  497. {"FTK_ATTR_BG_CENTER", FTK_ATTR_BG_CENTER},
  498. {"FTK_ATTR_BG_TILE", FTK_ATTR_BG_TILE},
  499. {"FTK_ATTR_BG_FOUR_CORNER", FTK_ATTR_BG_FOUR_CORNER},
  500. {"FTK_ATTR_NO_FOCUS", FTK_ATTR_NO_FOCUS},
  501. {"FTK_ATTR_INSENSITIVE", FTK_ATTR_INSENSITIVE},
  502. {"FTK_ATTR_FOCUSED", FTK_ATTR_FOCUSED},
  503. {"FTK_ATTR_QUIT_WHEN_CLOSE", FTK_ATTR_QUIT_WHEN_CLOSE},
  504. {"FTK_ATTR_FULLSCREEN", FTK_ATTR_FULLSCREEN},
  505. {"FTK_ALIGN_LEFT", FTK_ALIGN_LEFT},
  506. {"FTK_ALIGN_RIGHT", FTK_ALIGN_RIGHT},
  507. {"FTK_ALIGN_CENTER", FTK_ALIGN_CENTER},
  508. {"FTK_INPUT_NORMAL", FTK_INPUT_NORMAL},
  509. {"FTK_INPUT_DIGIT", FTK_INPUT_DIGIT},
  510. {"FTK_INPUT_ALPHA", FTK_INPUT_ALPHA},
  511. {"FTK_INPUT_URL", FTK_INPUT_URL},
  512. {"FTK_INPUT_EMAIL", FTK_INPUT_EMAIL},
  513. {"FTK_INPUT_ALL", FTK_INPUT_ALL},
  514. {"FTK_FILE_BROWER_APP", FTK_FILE_BROWER_APP},
  515. {"FTK_FILE_BROWER_SINGLE_CHOOSER", FTK_FILE_BROWER_SINGLE_CHOOSER},
  516. {"FTK_FILE_BROWER_MULTI_CHOOSER", FTK_FILE_BROWER_MULTI_CHOOSER},
  517. {NULL, 0},
  518. };
  519. static int ftk_xul_find_const(const char* name)
  520. {
  521. int i = 0;
  522. for(i = 0; s_var_conts[i].name != NULL; i++)
  523. {
  524. if(strncmp(s_var_conts[i].name, name, strlen(s_var_conts[i].name)) == 0)
  525. {
  526. return i;
  527. }
  528. }
  529. return -1;
  530. }
  531. static int ftk_xul_find_const_value(const char* name)
  532. {
  533. int i = 0;
  534. if (name[0] == '$')
  535. {
  536. name++;
  537. }
  538. i = ftk_xul_find_const(name);
  539. if (i < 0)
  540. {
  541. return 0;
  542. }
  543. else
  544. {
  545. return s_var_conts[i].value;
  546. }
  547. }
  548. static const char* ftk_xul_builder_preprocess_value(FtkXmlBuilder* thiz, const char* value)
  549. {
  550. int i = 0;
  551. int dst = 0;
  552. DECL_PRIV(thiz, priv);
  553. const char* iter = NULL;
  554. return_val_if_fail(value != NULL, NULL);
  555. for(iter = value; *iter && dst < sizeof(priv->processed_value); iter++)
  556. {
  557. if(*iter == '$')
  558. {
  559. char value[32] = {0};
  560. int len = sizeof(priv->processed_value)-dst;
  561. if((i = ftk_xul_find_getter(iter+1)) >= 0)
  562. {
  563. ftk_itoa(value, sizeof(value), s_var_getters[i].get(thiz));
  564. if(len > (int)strlen(value))
  565. {
  566. ftk_strcpy(priv->processed_value+dst, value);
  567. dst += strlen(priv->processed_value+dst);
  568. iter += strlen(s_var_getters[i].name);
  569. }
  570. continue;
  571. }
  572. else if((i = ftk_xul_find_const(iter+1)) >= 0)
  573. {
  574. ftk_itoa(value, sizeof(value), s_var_conts[i].value);
  575. if(len > (int)strlen(value))
  576. {
  577. ftk_strcpy(priv->processed_value+dst, value);
  578. dst += strlen(priv->processed_value+dst);
  579. iter += strlen(s_var_conts[i].name);
  580. }
  581. continue;
  582. }
  583. }
  584. priv->processed_value[dst++] = *iter;
  585. }
  586. priv->processed_value[dst] = '\0';
  587. return priv->processed_value;
  588. }
  589. static void ftk_xul_builder_init_widget_info(FtkXmlBuilder* thiz, const char** attrs, FtkWidgetCreateInfo* info)
  590. {
  591. int i = 0;
  592. const char* name = NULL;
  593. const char* value = NULL;
  594. DECL_PRIV(thiz, priv);
  595. return_if_fail(attrs != NULL && info != NULL);
  596. info->priv = priv;
  597. info->parent = priv->current;
  598. for(i = 0; attrs[i] != NULL; i += 2)
  599. {
  600. name = attrs[i];
  601. value = attrs[i+1];
  602. switch(name[0])
  603. {
  604. case 'i':
  605. {
  606. if(name[1] == 'd')
  607. {
  608. /*id*/
  609. info->id = atoi(value);
  610. }
  611. else if(name[1] == 'c')
  612. {
  613. if(name[4] == '\0')
  614. {
  615. /*icon*/
  616. info->icon = ftk_xul_load_image(info->priv->callbacks, value);
  617. }
  618. else if (name[4] == '_')
  619. {
  620. /*icon_position*/
  621. info->icon_position = atoi(value);
  622. }
  623. }
  624. break;
  625. }
  626. case 'x':
  627. {
  628. value = ftk_xul_builder_preprocess_value(thiz, value);
  629. info->x = (int)ftk_expr_eval(value);
  630. break;
  631. }
  632. case 'y':
  633. {
  634. value = ftk_xul_builder_preprocess_value(thiz, value);
  635. info->y = (int)ftk_expr_eval(value);
  636. break;
  637. }
  638. case 'w':
  639. {
  640. /*width*/
  641. value = ftk_xul_builder_preprocess_value(thiz, value);
  642. info->w = (int)ftk_expr_eval(value);
  643. break;
  644. }
  645. case 'h':
  646. {
  647. if(name[1] == '\0' || name[1] == 'e')
  648. {
  649. /*height*/
  650. value = ftk_xul_builder_preprocess_value(thiz, value);
  651. info->h = (int)ftk_expr_eval(value);
  652. }
  653. else if(name[1] == 'i')
  654. {
  655. /*hide_title*/
  656. info->hide_title = atoi(value);
  657. }
  658. break;
  659. }
  660. case 'a':
  661. {
  662. if(name[1] == 't')
  663. {
  664. /*attr*/
  665. info->attr = ftk_xul_find_const_value(value);
  666. }
  667. else if(name[1] == 'n')
  668. {
  669. /*anim_hint*/
  670. value = ftk_xul_builder_preprocess_value(thiz, value);
  671. ftk_strncpy(info->anim_hint, value, sizeof(info->anim_hint)-1);
  672. }
  673. else if (name[1] == 'l')
  674. {
  675. /*alignment*/
  676. info->alignment = ftk_xul_find_const_value(value);
  677. }
  678. break;
  679. }
  680. case 'v':
  681. {
  682. if(name[1] == 'a')
  683. {
  684. /*value*/
  685. info->value = value;
  686. }
  687. else if(name[1] == 'i')
  688. {
  689. /*visiable*/
  690. info->visible = atoi(value);
  691. }
  692. break;
  693. }
  694. case 'm':
  695. {
  696. /*max*/
  697. info->max_value = atoi(value);
  698. break;
  699. }
  700. case 'p':
  701. {
  702. /*page_delta*/
  703. info->page_delta = atoi(value);
  704. break;
  705. }
  706. case 'c':
  707. {
  708. /*checked*/
  709. info->checked = atoi(value);
  710. break;
  711. }
  712. case 'b':
  713. {
  714. if(strcmp(name, "bg[normal]") == 0)
  715. {
  716. info->gc[FTK_WIDGET_NORMAL].mask |= FTK_GC_BG;
  717. info->gc[FTK_WIDGET_NORMAL].bg = ftk_parse_color(value);
  718. }
  719. else if(strcmp(name, "bg[active]") == 0)
  720. {
  721. info->gc[FTK_WIDGET_ACTIVE].mask |= FTK_GC_BG;
  722. info->gc[FTK_WIDGET_ACTIVE].bg = ftk_parse_color(value);
  723. }
  724. else if(strcmp(name, "bg[focused]") == 0)
  725. {
  726. info->gc[FTK_WIDGET_FOCUSED].mask |= FTK_GC_BG;
  727. info->gc[FTK_WIDGET_FOCUSED].bg = ftk_parse_color(value);
  728. }
  729. else if(strcmp(name, "bg[disable]") == 0)
  730. {
  731. info->gc[FTK_WIDGET_INSENSITIVE].mask |= FTK_GC_BG;
  732. info->gc[FTK_WIDGET_INSENSITIVE].bg = ftk_parse_color(value);
  733. }
  734. else if(strcmp(name, "bg_image[normal]") == 0)
  735. {
  736. info->gc[FTK_WIDGET_NORMAL].mask |= FTK_GC_BITMAP;
  737. info->gc[FTK_WIDGET_NORMAL].bitmap = ftk_xul_load_image(info->priv->callbacks,value);
  738. }
  739. else if(strcmp(name, "bg_image[disable]") == 0)
  740. {
  741. info->gc[FTK_WIDGET_INSENSITIVE].mask |= FTK_GC_BITMAP;
  742. info->gc[FTK_WIDGET_INSENSITIVE].bitmap = ftk_xul_load_image(info->priv->callbacks,value);
  743. }
  744. else if(strcmp(name, "bg_image[active]") == 0)
  745. {
  746. info->gc[FTK_WIDGET_ACTIVE].mask |= FTK_GC_BITMAP;
  747. info->gc[FTK_WIDGET_ACTIVE].bitmap = ftk_xul_load_image(info->priv->callbacks,value);
  748. }
  749. else if(strcmp(name, "bg_image[focused]") == 0)
  750. {
  751. info->gc[FTK_WIDGET_FOCUSED].mask |= FTK_GC_BITMAP;
  752. info->gc[FTK_WIDGET_FOCUSED].bitmap = ftk_xul_load_image(info->priv->callbacks,value);
  753. }
  754. else
  755. {
  756. ftk_logd("%s: unknown %s\n", __func__, name);
  757. }
  758. break;
  759. }
  760. case 'f':
  761. {
  762. if(strcmp(name, "fg[normal]") == 0)
  763. {
  764. info->gc[FTK_WIDGET_NORMAL].mask |= FTK_GC_FG;
  765. info->gc[FTK_WIDGET_NORMAL].fg = ftk_parse_color(value);
  766. }
  767. else if(strcmp(name, "fg[active]") == 0)
  768. {
  769. info->gc[FTK_WIDGET_ACTIVE].mask |= FTK_GC_FG;
  770. info->gc[FTK_WIDGET_ACTIVE].fg = ftk_parse_color(value);
  771. }
  772. else if(strcmp(name, "fg[focused]") == 0)
  773. {
  774. info->gc[FTK_WIDGET_FOCUSED].mask |= FTK_GC_FG;
  775. info->gc[FTK_WIDGET_FOCUSED].fg = ftk_parse_color(value);
  776. }
  777. else if(strcmp(name, "fg[disable]") == 0)
  778. {
  779. info->gc[FTK_WIDGET_INSENSITIVE].mask |= FTK_GC_FG;
  780. info->gc[FTK_WIDGET_INSENSITIVE].fg = ftk_parse_color(value);
  781. }
  782. else if(strcmp(name, "filter") == 0)
  783. {
  784. info->filter = value;
  785. }
  786. else if(strcmp(name, "font") == 0)
  787. {
  788. info->font = value;
  789. }
  790. else
  791. {
  792. ftk_logd("%s: unknown %s\n", __func__, name);
  793. }
  794. break;
  795. }
  796. case 't':
  797. {
  798. if (name[1] == 'i')
  799. {
  800. /*tips*/
  801. info->tips = value;
  802. }
  803. else if (name[1] == 'y')
  804. {
  805. /*type*/
  806. info->type = ftk_xul_find_const_value(value);
  807. }
  808. break;
  809. }
  810. default:break;/*TODO: handle other attrs*/
  811. }
  812. }
  813. return;
  814. }
  815. static void ftk_xul_builder_reset_widget_info(FtkXmlBuilder* thiz, FtkWidgetCreateInfo* info)
  816. {
  817. int i = 0;
  818. for(i = 0; i < FTK_WIDGET_STATE_NR;i++)
  819. {
  820. ftk_gc_reset(info->gc+i);
  821. }
  822. return;
  823. }
  824. static void ftk_xul_builder_on_start(FtkXmlBuilder* thiz, const char* tag, const char** attrs)
  825. {
  826. DECL_PRIV(thiz, priv);
  827. FtkWidget* widget = NULL;
  828. FtkWidgetCreateInfo info = {0};
  829. const WidgetCreator* creator = ftk_xul_find_creator(tag);
  830. priv->meet_start_tag = 0;
  831. return_if_fail(creator != NULL && creator->create != NULL && attrs != NULL && thiz != NULL);
  832. ftk_xul_builder_init_widget_info(thiz, attrs, &info);
  833. if (creator->is_widget)
  834. {
  835. if (!priv->prev_is_widget && priv->current != NULL)
  836. {
  837. info.parent = ftk_widget_parent(priv->current);
  838. }
  839. if((widget = creator->create(&info)) != NULL)
  840. {
  841. ftk_widget_set_id(widget, info.id);
  842. ftk_widget_set_attr(widget, info.attr);
  843. if(info.gc[FTK_WIDGET_NORMAL].mask & FTK_GC_BG)
  844. {
  845. ftk_widget_unset_attr(widget, FTK_ATTR_TRANSPARENT);
  846. }
  847. ftk_widget_set_gc(widget, FTK_WIDGET_NORMAL, info.gc+FTK_WIDGET_NORMAL);
  848. ftk_widget_set_gc(widget, FTK_WIDGET_FOCUSED, info.gc+FTK_WIDGET_FOCUSED);
  849. ftk_widget_set_gc(widget, FTK_WIDGET_ACTIVE, info.gc+FTK_WIDGET_ACTIVE);
  850. ftk_widget_set_gc(widget, FTK_WIDGET_INSENSITIVE, info.gc+FTK_WIDGET_INSENSITIVE);
  851. if(info.anim_hint[0])
  852. {
  853. ftk_window_set_animation_hint(widget, info.anim_hint);
  854. }
  855. if(info.font != NULL)
  856. {
  857. ftk_widget_set_font(widget, info.font);
  858. }
  859. ftk_widget_show(widget, info.visible);
  860. }
  861. ftk_xul_builder_reset_widget_info(thiz, &info);
  862. return_if_fail(widget != NULL);
  863. priv->current = widget;
  864. priv->meet_start_tag = 1;
  865. priv->prev_is_widget = 1;
  866. if(priv->root == NULL)
  867. {
  868. priv->root = widget;
  869. }
  870. }
  871. else
  872. {
  873. creator->create(&info);
  874. ftk_xul_builder_reset_widget_info(thiz, &info);
  875. priv->meet_start_tag = 0;
  876. priv->prev_is_widget = 0;
  877. }
  878. return;
  879. }
  880. static void ftk_xul_builder_on_end(FtkXmlBuilder* thiz, const char* tag)
  881. {
  882. DECL_PRIV(thiz, priv);
  883. if(priv->meet_start_tag)
  884. {
  885. priv->current = ftk_widget_parent(priv->current);
  886. }
  887. return;
  888. }
  889. static void ftk_xul_builder_destroy(FtkXmlBuilder* thiz)
  890. {
  891. if(thiz != NULL)
  892. {
  893. FTK_ZFREE(thiz, sizeof(FtkXmlBuilder) + sizeof(PrivInfo));
  894. }
  895. return;
  896. }
  897. static FtkXmlBuilder* ftk_xul_builder_create(void)
  898. {
  899. FtkXmlBuilder* thiz = FTK_NEW_PRIV(FtkXmlBuilder);
  900. if(thiz != NULL)
  901. {
  902. thiz->on_start_element = ftk_xul_builder_on_start;
  903. thiz->on_end_element = ftk_xul_builder_on_end;
  904. thiz->destroy = ftk_xul_builder_destroy;
  905. }
  906. return thiz;
  907. }
  908. static const char* ftk_text_no_translate(void* ctx, const char* text)
  909. {
  910. return text;
  911. }
  912. static FtkBitmap* ftk_default_load_image(void* ctx, const char* filename)
  913. {
  914. return ftk_bitmap_factory_load(ftk_default_bitmap_factory(), filename);
  915. }
  916. static const FtkXulCallbacks default_callbacks =
  917. {
  918. NULL,
  919. ftk_text_no_translate,
  920. ftk_default_load_image
  921. };
  922. FtkWidget* ftk_xul_load_ex(const char* xml, int length, FtkXulCallbacks* callbacks)
  923. {
  924. FtkWidget* widget = NULL;
  925. FtkXmlParser* parser = NULL;
  926. FtkXmlBuilder* builder = NULL;
  927. return_val_if_fail(xml != NULL, NULL);
  928. parser = ftk_xml_parser_create();
  929. return_val_if_fail(parser != NULL, NULL);
  930. builder = ftk_xul_builder_create();
  931. if(builder != NULL)
  932. {
  933. PrivInfo* priv = (PrivInfo*)builder->priv;
  934. priv->callbacks = callbacks;
  935. priv->prev_is_widget = 0;
  936. ftk_xml_parser_set_builder(parser, builder);
  937. ftk_xml_parser_parse(parser, xml, length);
  938. widget = priv->root;
  939. }
  940. ftk_xml_builder_destroy(builder);
  941. ftk_xml_parser_destroy(parser);
  942. return widget;
  943. }
  944. FtkWidget* ftk_xul_load(const char* xml, int length)
  945. {
  946. return ftk_xul_load_ex(xml, length, (FtkXulCallbacks*)&default_callbacks);
  947. }
  948. FtkWidget* ftk_xul_load_file(const char* filename, FtkXulCallbacks* callbacks)
  949. {
  950. FtkMmap* m = NULL;
  951. FtkWidget* widget = NULL;
  952. return_val_if_fail(filename != NULL, NULL);
  953. if((m = ftk_mmap_create(filename, 0, -1)) != NULL)
  954. {
  955. widget = ftk_xul_load_ex((const char*)ftk_mmap_data(m), ftk_mmap_length(m), callbacks);
  956. ftk_mmap_destroy(m);
  957. }
  958. ftk_logd("%s: %p %s\n", __func__, widget, filename);
  959. return widget;
  960. }