PageRenderTime 138ms CodeModel.GetById 80ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 1ms

/src/ftk_xul.c

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