写代码很多年了,接触最多的是GUI。无论是windows的还是linux,无论是PC的还是嵌入式的,写GUI的时候, 很多GUI库会提供一些控件或者widget,供程序使用。而实际上,这些远远不够,要做出漂亮的GUI不容易,需要做很多定制。
传统的理念,无论是用C++或者java等面向对象开发的,还是用C语言开发的,总会遵循面向对象的思路,从一个根继承若干种类的控件。但是这种思路,能够方便一些定制,但是还是不够方便。最好的方法,是组合的方法。
组合的方法是把多个界面的元素组合成一个元素,例如,我们把button和text组合,就是文本button,而把button和image组合,就是image button。更妙的是,我们可以用xml来描述:
<button>
<image/>
</button>
如果做的足够好,创建一个新的控件甚至不需要编写一行代码,只要写好xml文件就可以了。
如果能够实现这一点,那么,复杂的界面,只需要有限的元素就可以组合出万千变化,对于GUI编程来说,是很大的福音。
观察GUI的类型,大致有3种
1. 显示用的元素,如文本、图片和各种形状
2. 交互控制的元素,可以响应鼠标、键盘事件
3. 布局元素,用于控制位置信息的
在GUI中,存在一批不能分解的元素,如点、线、填充区域,空白,类似button的事件处理元素等。我们完全可以使用xml来描述。
比如,一个有阳雕效果的矩形---通常被用来作为pushbutton的背景---用xml描述出来就是
<template name="OutSideRect">
<property name="top" type="int"/>
<property name="left" type="int"/>
<property name="right" type="int"/>
<property name="bottom" type="int"/>
<property name="color" type="Color"/>
<HLine x0="$left" x1="$right" y="$top" color="drak($color_border)"/>
<HLine x0="$left + 1" x1="$right-1" y="$top" color="light($color_border)"/>
...
</template>
上面的代码,用一个template描述了OutSideRect元素,这个元素有属性top, left, right, bottom和color,其绘制方法可以用HLine表示水平线VLine表示垂直线和Fill来表示。
这个元素就可以被其他元素使用,用于组合,比如,用于button控件
<template name="Button">
<property name="top" type="int"/>
<property name="left" type="int"/>
<property name="right" type="int"/>
<property name="bottom" type="int"/>
<property name="bkcolor" type="bkcolor"/>
<property name="fgcolor" type="fgcolor"/>
<OutSideRect color="$bkcolor" top="$top" left="$left" right="$right" bottom="$bottom"/>
<Text color="$fgcolor" top="$top" left="$left" right="$right" bottom="$bottom"/>
</template>
这样一个button,包含了OutSideRect和Text两个对象,其位置和button的一致,而颜色却各有不同。
上面的描述仅仅是简单的位置描述,还 未设计事件的处理。
这正可用的组合和描述方法,还需要支持
* 继承:继承扩展还是非常有用的,可以方便元素的定义
* 事件的处理,并随事件处理,需要增加一些嵌入代码,用于粘合各个对象间的关系
在编程语言发展中,xml是属于DSL(领域描述语言)的范畴,DSL相对于命令式语言的优点是,DSL强调的是What, 而不是How。
而命令式语言必须强调How,而What被隐藏到how之中了。
我们的这种思想,就在于,通过描述一个控件的构成,而忽略应该如何实现这种构成。
我们通过一个工具,把xml语言翻译成对应的C代码,这样,在不写命令式代码或者写很少代码的情况下,就快速创建出一个控件来使用。
如果能够实现这个目标,一个GUI库可能只需要提供基本的窗口管理,提供基本的元素实现,以及元素间合成的必要支持,就可以实现一个很好很漂亮的GUI了。
而且,它可以很容易的被裁剪和移植,肯定会很适合嵌入式使用的。