ccdui.h 定义了如何创建一个窗口并附加组件树,此头文件将定义组件树的组成和快速构造它的语法。
注意:本文用到了AutoTree构造语法,这不是标准C的语法,而是为了更简单的实现特定功能创造的语法。
ccdui.h定义了一些常用的组件/元素,在这篇文章中将介绍组件树的构成和如何正确的创建一个可具有多实例的合理的组件树。
组件树是一个由若干个具有亲子关系的元素构成的一棵树。在ccdui的基本API中,并没有将数据(Model)和视图(View)分离,所以组件树包括了视图的逻辑结构和视图所需的数据。在ccdui中,任何的元素都以如下形式表示:
AutoTree item = @{
type: "元素的类型",
若干属性字段...,
sub: [
{
...(元素)
}
]
};
其中,sub代表当前元素的子元素,出现在各类容器类元素中。
一般情况下,要交给窗口展示的组件树以component(类型)作为根元素,所以它的构造方法应该类似于:
xxxxxxxxxx
例1:
AutoTree item = @{
type: "component",
sub: [
{
type: "label",
text: "Hello world"
}
]
};
上述组件树为一个component根结点,显示在窗口中将展示“Hello World”。
您可能已经注意到,如果完全的使用类json语法来定义一整个组件,那么代码量将非常大。所以,首先我们可以自然的想到将一些常用组件提取函数:
xxxxxxxxxx
AutoTree label(char *text) {
AutoTree item = @{
type: "label"
}
}
那么,例1就可以改写为
xxxxxxxxxx
AutoTree item = @{
type: "component",
sub: [
label("Hello world")
]
};
对于容器类元素,可以提取:
xxxxxxxxxx
AutoTree component(AutoTree mutating) {
type: "component",
sub: mutating
};
由于AutoTree的@构造只适用于初始化构造时,并不适用于函数参数,所以以下的语句是不合法的:
xxxxxxxxxx
AutoTree item = component(@[
label("Hello world")
]);
所以,为了解决这个问题,引入后置数据语法:由冒号开头,连接函数名,函数名后跟一个AutoTree数组。
xxxxxxxxxx
AutoTree item = :component [
label("Hello world")
];
另外,你可能想到,这样的设置缺乏了自定义办法。label函数仅定义了一个标准的、通用的文本标签,如果想要定义带有不同属性的标签,那就要把各种不同的属性组合都写成不同的函数,这不合理。所以,继续修改AutoTree的@构造语法,加入后置属性修改语法:在任何一个返回键值对函数调用的末尾,可以再跟一个{}键值对,表示对于已有的函数返回键值对进行一些修改。
xxxxxxxxxx
AutoTree item = :component [
label("Hello world") {
color: "white",
fontSize: 30
},
label("Hello again") {
color: "red",
fontSize: 20
}
];
这样,就可以基于基本的label()模板,优雅的定义出各种不同属性的label了。
事件是部分元素具有的属性,属性名称是action,值为一个符合Action函数指针定义的函数指针。比如,当按钮被点击时,action所指向的函数将会被调用。在很多情况下,您的事件接收函数可能同时被多个action字段引用(比如计算器的众多按钮指向同一个函数),可以通过参数来判断具体是哪个元素触发的事件。Action函数指针的定义如下:
xxxxxxxxxx
typedef void (* Action)(Action root, Action this);
this表示触发事件的具体按钮,root表示该按钮的向上查找第一个类型为component的双亲元素。
元素指的是一个组成UI的基本控件,比如一个文本,按钮,输入框等等,由上述函数定义。并且,由若干个元素组成的组件依然是元素,比如一个vstack元素可能包括了若干个子元素。考察元素的定义,一个合理的UI似乎只需要使用若干个元素构成的树即可,但是如果加入事件,情况可能就有些复杂。
考虑一种元素,例如选择框,用户点击一次为白色,再点击一次为黑色。这个元素需要被多次使用,那么利用Action函数可以标识这个选择框到底属于哪个上级component,继而可以改变相应component下某个节点的color属性。component内部元素事件只管理上级component内部组件的component元素,对component元素及其内部元素的整体称为组件,它只管理自身元素,并可以创建多个实例,每个实例都维护自己内部的节点。对于每个传递到ccd_ui_attach中的组件树参数,建议其根节点为component。
在ccduicomp.h中定义了3个基本的布局元素,分别是hstack vstack zstack,它们分别表示其内部的元素在x方向、y方向和垂直方向顺序分布。(垂直方向:例如底层是背景,在背景上显示文本等多层视图结构)。可以综合使用这三种布局元素来完成布局。另外,还可以使用spacer元素来填充其双亲stack元素的剩余空间,从而占满屏幕。
属性名 | 值类型 | 含义 |
---|---|---|
text | 任意可转换为字符串的节点 | 元素上的文本 |
action | Action函数指针 | 元素相关的事件 |
color | 颜色名或Hex颜色 | 元素颜色 |
colorfg | 颜色名或Hex颜色 | 元素前景颜色 |
colorbg | 颜色名或Hex颜色 | 元素背景颜色 |
align | topLeft top topRight left center right bottomLeft bottom bottomRight | 元素对齐位置 |
space | 数字 | Spacer的最小长度 |
cornerRadius | 数字 | 圆角半径 |
borderColor | 颜色名或Hex颜色 | 边框颜色 |
borderWidth | 数字 | 边框宽度 |
paddingTop | 数字 | 内边距上方 |
paddingLeft | 数字 | 内边距左侧 |
paddingRight | 数字 | 内边距右侧 |
paddingBottom | 数字 | 内边距下方 |
fontSize | 数字 | 字体大小 |
height | 数字 | 高度 |
placeholder | 任意可转换为字符串的节点 | 占位符文本 |
image | URL地址或项目路径(例: items.images/pic1) | 背景图片 |
autotree.h 定义了组件树的存储方式,并增加了快速构造语法
ccdui.h 定义如何创建一个窗口、附加组件树、打开窗口以及进入窗口消息循环的方法