Skip to content

Commit d5e162c

Browse files
committed
feat(builder): <resource> support load xml file
1 parent 3249490 commit d5e162c

File tree

8 files changed

+116
-51
lines changed

8 files changed

+116
-51
lines changed

build/windows/LCUITest/LCUITest.vcxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,17 @@
100100
</ItemDefinitionGroup>
101101
<ItemGroup>
102102
<ClCompile Include="..\..\..\test\test.c" />
103+
<ClCompile Include="..\..\..\test\test_charset.c" />
103104
<ClCompile Include="..\..\..\test\test_css_parser.c" />
104105
<ClCompile Include="..\..\..\test\test_font_load.c" />
105106
<ClCompile Include="..\..\..\test\test_image_reader.c" />
106107
<ClCompile Include="..\..\..\test\test_string.c" />
108+
<ClCompile Include="..\..\..\test\test_textview_resize.c" />
107109
<ClCompile Include="..\..\..\test\test_thread.c" />
108110
<ClCompile Include="..\..\..\test\test_widget_flex_layout.c" />
109111
<ClCompile Include="..\..\..\test\test_widget_inline_block_layout.c" />
110112
<ClCompile Include="..\..\..\test\test_widget_layout.c" />
113+
<ClCompile Include="..\..\..\test\test_widget_opacity.c" />
111114
<ClCompile Include="..\..\..\test\test_widget_rect.c" />
112115
<ClCompile Include="..\..\..\test\test_xml_parser.c" />
113116
</ItemGroup>

build/windows/LCUITest/LCUITest.vcxproj.filters

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@
4848
<ClCompile Include="..\..\..\test\test_thread.c">
4949
<Filter>源文件</Filter>
5050
</ClCompile>
51+
<ClCompile Include="..\..\..\test\test_charset.c">
52+
<Filter>源文件</Filter>
53+
</ClCompile>
54+
<ClCompile Include="..\..\..\test\test_widget_opacity.c">
55+
<Filter>源文件</Filter>
56+
</ClCompile>
57+
<ClCompile Include="..\..\..\test\test_textview_resize.c">
58+
<Filter>源文件</Filter>
59+
</ClCompile>
5160
</ItemGroup>
5261
<ItemGroup>
5362
<ClInclude Include="..\..\..\test\test.h">

src/gui/builder.c

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* ***************************************************************************
1+
/* ***************************************************************************
22
* builder.c -- the GUI build module, parse UI config code and build UI.
33
*
44
* Copyright (c) 2018, Liu chao <lc-soft@live.cn> All rights reserved.
@@ -43,7 +43,7 @@
4343
#include <libxml/xmlmemory.h>
4444
#include <libxml/parser.h>
4545

46-
#define PropNameIs(type) (xmlStrcasecmp(prop->name, BAD_CAST type) == 0)
46+
#define PropNameIs(PROP, NAME) (xmlStrcasecmp(PROP->name, (xmlChar*)NAME) == 0)
4747

4848
enum ParserID {
4949
ID_ROOT,
@@ -71,9 +71,10 @@ typedef struct Parser {
7171

7272
struct XMLParserContextRec_ {
7373
int id;
74-
LCUI_Widget widget;
7574
LCUI_Widget root;
76-
ParserPtr parent;
75+
LCUI_Widget widget;
76+
LCUI_Widget parent_widget;
77+
ParserPtr parent_parser;
7778
const char *space;
7879
};
7980

@@ -82,10 +83,15 @@ static struct ModuleContext {
8283
RBTree parsers;
8384
} self;
8485

86+
#define EXIT(CODE) code = CODE; goto exit;
87+
8588
/** 解析<resource>元素,根据相关参数载入资源 */
8689
static int ParseResource(XMLParserContext ctx, xmlNodePtr node)
8790
{
91+
8892
xmlAttrPtr prop;
93+
94+
int code = PB_NEXT;
8995
char *prop_val, *type = NULL, *src = NULL;
9096

9197
if (node->type != XML_ELEMENT_NODE) {
@@ -94,9 +100,9 @@ static int ParseResource(XMLParserContext ctx, xmlNodePtr node)
94100
prop = node->properties;
95101
while (prop) {
96102
prop_val = (char*)xmlGetProp(node, prop->name);
97-
if (PropNameIs("type")) {
103+
if (PropNameIs(prop, "type")) {
98104
type = prop_val;
99-
} else if (PropNameIs("src")) {
105+
} else if (PropNameIs(prop, "src")) {
100106
src = prop_val;
101107
} else {
102108
xmlFree(prop_val);
@@ -107,25 +113,48 @@ static int ParseResource(XMLParserContext ctx, xmlNodePtr node)
107113
return PB_WARNING;
108114
}
109115
if (strstr(type, "application/font-")) {
110-
LCUIFont_LoadFile(src);
111-
} else if (strstr(type, "text/css")) {
116+
if (LCUIFont_LoadFile(src) < 1) {
117+
EXIT(PB_WARNING);
118+
}
119+
} else if (strcmp(type, "text/css") == 0) {
112120
if (src) {
113-
LCUI_LoadCSSFile(src);
121+
if (LCUI_LoadCSSFile(src) != 0) {
122+
EXIT(PB_WARNING);
123+
}
114124
}
115125
for (node = node->children; node; node = node->next) {
116126
if (node->type != XML_TEXT_NODE) {
117127
continue;
118128
}
119129
LCUI_LoadCSSString((char*)node->content, ctx->space);
120130
}
131+
} else if (strcmp(type, "text/xml") == 0) {
132+
LCUI_Widget pack;
133+
if (!src) {
134+
EXIT(PB_WARNING);
135+
}
136+
pack = LCUIBuilder_LoadFile(src);
137+
if (!pack) {
138+
EXIT(PB_WARNING);
139+
}
140+
if (ctx->parent_widget) {
141+
Widget_Append(ctx->parent_widget, pack);
142+
} else if (ctx->root) {
143+
Widget_Append(ctx->root, pack);
144+
} else {
145+
Widget_Destroy(pack);
146+
EXIT(PB_WARNING);
147+
}
148+
Widget_Unwrap(pack);
121149
}
150+
exit:
122151
if (src) {
123152
xmlFree(src);
124153
}
125154
if (type) {
126155
xmlFree(type);
127156
}
128-
return PB_NEXT;
157+
return code;
129158
}
130159

131160
/** 解析<ui>元素,主要作用是创建一个容纳全部部件的根级部件 */
@@ -134,7 +163,7 @@ static int ParseUI(XMLParserContext ctx, xmlNodePtr node)
134163
if (node->type != XML_ELEMENT_NODE) {
135164
return PB_NEXT;
136165
}
137-
if (ctx->parent && ctx->parent->id != ID_ROOT) {
166+
if (ctx->parent_parser && ctx->parent_parser->id != ID_ROOT) {
138167
return PB_ERROR;
139168
}
140169
ctx->widget = LCUIWidget_New(NULL);
@@ -149,8 +178,8 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
149178
char *prop_val = NULL, *prop_name;
150179
LCUI_Widget w = NULL, parent = ctx->widget;
151180

152-
if (ctx->parent && ctx->parent->id != ID_UI &&
153-
ctx->parent->id != ID_WIDGET) {
181+
if (ctx->parent_parser && ctx->parent_parser->id != ID_UI &&
182+
ctx->parent_parser->id != ID_WIDGET) {
154183
return PB_ERROR;
155184
}
156185
switch (node->type) {
@@ -178,7 +207,7 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
178207
xmlFree(prop_val);
179208
}
180209
prop_val = (char*)xmlGetProp(node, prop->name);
181-
if (PropNameIs("type")) {
210+
if (PropNameIs(prop, "type")) {
182211
DEBUG_MSG("widget: %p, set type: %s\n", w, prop_val);
183212
w->proto = LCUIWidget_GetPrototype(prop_val);
184213
if (w->proto && w->proto->init) {
@@ -188,11 +217,11 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
188217
w->type = strdup2(prop_val);
189218
}
190219
continue;
191-
} else if (PropNameIs("id")) {
220+
} else if (PropNameIs(prop, "id")) {
192221
DEBUG_MSG("widget: %p, set id: %s\n", w, prop_val);
193222
Widget_SetId(w, prop_val);
194223
continue;
195-
} else if (PropNameIs("class")) {
224+
} else if (PropNameIs(prop, "class")) {
196225
DEBUG_MSG("widget: %p, add class: %s\n", w, prop_val);
197226
Widget_AddClass(w, prop_val);
198227
continue;
@@ -243,19 +272,21 @@ static void ParseNode(XMLParserContext ctx, xmlNodePtr node)
243272
{
244273
ParserPtr p;
245274
XMLParserContextRec cur_ctx;
275+
246276
for (; node; node = node->next) {
247277
if (node->type == XML_ELEMENT_NODE) {
248278
p = RBTree_CustomGetData(&self.parsers, node->name);
249279
} else {
250-
p = ctx->parent;
280+
p = ctx->parent_parser;
251281
}
252282
if (!p) {
253283
continue;
254284
}
255285
cur_ctx = *ctx;
286+
cur_ctx.parent_widget = ctx->widget;
256287
switch (p->parse(&cur_ctx, node)) {
257288
case PB_ENTER:
258-
cur_ctx.parent = p;
289+
cur_ctx.parent_parser = p;
259290
ParseNode(&cur_ctx, node->children);
260291
break;
261292
case PB_NEXT: break;
@@ -285,10 +316,7 @@ LCUI_Widget LCUIBuilder_LoadString(const char *str, int size)
285316
xmlNodePtr cur;
286317
XMLParserContextRec ctx;
287318

288-
ctx.root = NULL;
289-
ctx.widget = NULL;
290-
ctx.parent = NULL;
291-
ctx.space = NULL;
319+
memset(&ctx, 0, sizeof(ctx));
292320
doc = xmlParseMemory(str, size);
293321
if (!doc) {
294322
LOG("[builder] Failed to parse xml form memory\n");
@@ -321,9 +349,7 @@ LCUI_Widget LCUIBuilder_LoadFile(const char *filepath)
321349
xmlNodePtr cur;
322350
XMLParserContextRec ctx;
323351

324-
ctx.root = NULL;
325-
ctx.widget = NULL;
326-
ctx.parent = NULL;
352+
memset(&ctx, 0, sizeof(ctx));
327353
ctx.space = filepath;
328354
doc = xmlParseFile(filepath);
329355
if (!doc) {

test/helloworld.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
22
<lcui-app>
33
<resource type="text/css" src="helloworld.css"/>
4-
<resource type="application/font-ttf" src="C:/windows/fonts/segoeui.ttf"/>
5-
<resource type="application/font-ttf" src="C:/windows/fonts/segoeuib.ttf"/>
6-
<resource type="application/font-ttf" src="C:/windows/fonts/segoeuii.ttf"/>
7-
<resource type="application/font-ttf" src="C:/windows/fonts/segoeuiz.ttf"/>
84
<ui>
95
<widget id="text-hello" type="textview" class="text-hello">
106
[i][color=#f00]Hello[/color][/i], [b][color=#fff][bgcolor=#f00]World![/bgcolor][/color][/b]

test/test_charset.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include <wchar.h>
1+
#include <wchar.h>
22
#include <string.h>
33
#include <LCUI_Build.h>
44
#include <LCUI/util/logger.h>

test/test_xml_parser.c

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,60 @@
55
#include <LCUI/gui/builder.h>
66
#include "test.h"
77

8-
static int check_widget_attribute( void )
8+
static int check_widget_attribute(void)
99
{
1010
int ret = 0;
1111
LCUI_Widget w;
1212

13-
w = LCUIWidget_GetById( "test-attr-disabed-1" );
14-
CHECK_WITH_TEXT( "check element-1 is disabled", w->disabled );
15-
w = LCUIWidget_GetById( "test-attr-disabed-2" );
16-
CHECK_WITH_TEXT( "check element-2 is disabled", w->disabled );
17-
w = LCUIWidget_GetById( "test-attr-disabed-3" );
18-
CHECK_WITH_TEXT( "check element-3 is disabled", w->disabled );
19-
w = LCUIWidget_GetById( "test-attr-disabed-4" );
20-
CHECK_WITH_TEXT( "check element-4 is normal", !w->disabled );
13+
w = LCUIWidget_GetById("test-attr-disabled-1");
14+
CHECK_WITH_TEXT("check element-1 is disabled", w->disabled);
15+
w = LCUIWidget_GetById("test-attr-disabled-2");
16+
CHECK_WITH_TEXT("check element-2 is disabled", w->disabled);
17+
w = LCUIWidget_GetById("test-attr-disabled-3");
18+
CHECK_WITH_TEXT("check element-3 is disabled", w->disabled);
19+
w = LCUIWidget_GetById("test-attr-disabled-4");
20+
CHECK_WITH_TEXT("check element-4 is normal", !w->disabled);
21+
22+
return ret;
23+
}
24+
25+
static int check_widget_loaded_from_nested_xml(void)
26+
{
27+
int ret = 0;
28+
LCUI_Widget w;
29+
30+
w = LCUIWidget_GetById("test-nested-1");
31+
CHECK_WITH_TEXT("check test-nested-1 should exist", w);
32+
w = LCUIWidget_GetById("test-nested-2");
33+
CHECK_WITH_TEXT("check test-nested-2 should exist", w);
34+
w = LCUIWidget_GetById("test-nested-3");
35+
CHECK_WITH_TEXT("check test-nested-3 should exist", w);
36+
w = LCUIWidget_GetById("test-nested-4");
37+
CHECK_WITH_TEXT("check test-nested-4 should exist", w);
38+
2139
return ret;
2240
}
2341

24-
int test_xml_parser( void )
42+
int test_xml_parser(void)
2543
{
2644
int ret = 0;
2745
LCUI_Widget root, pack;
2846

2947
LCUI_Init();
30-
TEST_LOG( "test widget layout\n" );
31-
LCUIDisplay_SetSize( 960, 680 );
48+
TEST_LOG("test widget layout\n");
49+
LCUIDisplay_SetSize(960, 680);
3250
root = LCUIWidget_GetRoot();
33-
CHECK( pack = LCUIBuilder_LoadFile( "test_xml_parser.xml" ) );
34-
if( !pack ) {
51+
CHECK(pack = LCUIBuilder_LoadFile("test_xml_parser.xml"));
52+
if (!pack) {
3553
LCUI_Destroy();
3654
return ret;
3755
}
38-
Widget_UpdateStyle( root, TRUE );
39-
Widget_Append( root, pack );
40-
Widget_Unwrap( pack );
56+
Widget_UpdateStyle(root, TRUE);
57+
Widget_Append(root, pack);
58+
Widget_Unwrap(pack);
4159
LCUIWidget_Update();
4260
ret += check_widget_attribute();
61+
ret += check_widget_loaded_from_nested_xml();
4362
LCUI_Destroy();
4463
return ret;
4564
}

test/test_xml_parser.nested.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<lcui-app>
3+
<ui>
4+
<w id="test-nested-1" type="textview">Element 1 from nested xml file</w>
5+
<w id="box">
6+
<w id="test-nested-2" type="textview">Element 2 from nested xml file</w>
7+
<w id="test-nested-3" type="textview">Element 3 from nested xml file</w>
8+
<w id="test-nested-4" type="textview">Element 4 from nested xml file</w>
9+
</w>
10+
</ui>
11+
</lcui-app>

test/test_xml_parser.xml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
22
<lcui-app>
33
<ui>
4-
<w id="test-attr-disabed-1" type="textview" disabled="">Disabed element 1</w>
5-
<w id="test-attr-disabed-2" type="textview" disabled="disabled">Disabed element 2</w>
6-
<w id="test-attr-disabed-3" type="textview" disabled="test">Disabed element 3</w>
7-
<w id="test-attr-disabed-4" type="textview" disabled="false">Normal element 1</w>
4+
<w id="test-attr-disabled-1" type="textview" disabled="">Disabed element 1</w>
5+
<w id="test-attr-disabled-2" type="textview" disabled="disabled">Disabed element 2</w>
6+
<w id="test-attr-disabled-3" type="textview" disabled="test">Disabed element 3</w>
7+
<resource type="text/xml" src="test_xml_parser.nested.xml" />
8+
<w id="test-attr-disabled-4" type="textview" disabled="false">Normal element 4</w>
89
</ui>
910
</lcui-app>

0 commit comments

Comments
 (0)