一,WidgetBase及其作用
1,结构体的定义
struct WidgetBase {
const AEEVTBL(IWidget) *pvt;
int nRefs;
IModule * piModule;
WExtent extent;
IContainer * piContainer;
IModel * piModel;
HandlerDesc hd;
PFNHANDLER pfnDefHandler;
// view model
IModel * piViewModel;
};
2,各字段的说明
字段名
说明
pvt
虚函数表的指针
nRefs
引用计数
piModule
所属的Module的指针
extent
Widget的大小,宽度,高度
piContainer
widget所属container的指针
piModel
Widget为根据MVC模型而作的,Model的指针
hd
在该widget上有event发生时,调用该处理函数。
pfnDefHandler
默认的event处理函数
piViewModel
3,该结构体定义了所有widget公用的数据成员。当然也提供了公用的函数,如WidgetBase_XXX等函数群。具体的widget 的实现类,都以该结构体作为第一个成员。
二,ContainerBase及其作用
1,container的简单说明
widget的容器,而container又可以看作是一种特殊的widget。这里就是一个composite模式。
2,WidgetNode
Container中的所有widget的相关信息放在一个双向链表中。链表的节点的定义如下:
struct WidgetNode {
WidgetNode * pNext;
WidgetNode * pPrev;
IWidget * piWidget;
AEERect rc;
// if non-null, then this widget is raised
IXYContainer * pixyRaise; // xy container that widget is raised to
#if defined(OPTIMIZ3)
AEERect rcDraw;
#endif
flg fVisible : 1;
flg fDraw : 1;
};
pNext,pPrev构成了双向链表;piWidget就是容器中的一个widget的指针;rc代表了该widget的位置,及大小。
对容器的操作,如添加widget,删除widget,查找widget,遍历所有的widget等,都映射为对该链表的操作。
3,结构体定义
struct ContainerBase
{
AEEVTBL(IContainer) * pvt;
uint32 nRefs;
IModule * piModule;
IModel * piModel;
WExtent extent;
IContainer * piParent;
IWidget widget;
AEEVTBL(IWidget) vtWidget;
Border border;
IModel * piViewModel;
HandlerDesc hd;
PFNHANDLER pfnDefHandler;
WidgetNode head;
…
};
4,字段说明
字段
说明
pvt
指向IContainer的虚函数表
从nRefs 到
piParent,
及hr和
pfnDefHandler
同WidgetBase的意义完全相同,因为要把Container看作一个普通的widget
widget
IWidgetVtbl *pvt ; 指向结构体的下一个字段vtWidget;就是通过这一个虚函数表,是该container可以被认为是一个普通的widget。当调用ICONTAINER_QueryInterface( IWidget )时,返回该指针的地址。
ContainerBase * pMe ; 其实就是this指针
vtWidget
Widget的虚函数表,通过该表,使container可以被认为是一个普通的widget。
head
包含的Widget组成的链表
摘抄的代码如下:
int ContainerBase_QueryInterface(IContainer *po, AEECLSID id, void **ppo)
{
if ((id == AEEIID_WIDGET)
|| (id == AEEIID_HANDLER)) {
*ppo = &me->widget;
ICONTAINER_AddRef(po);
return SUCCESS;
}
}
当客户通过该指针调用IWidget接口的方法时,
(*(IWidgetVtbl**)(void*)ptr)->AddRef();
*ptr为字段pvt的值,即指向IWidgetVtbl结构体的指针。上述语句只不过是添加了强制类型转换。
通过这里我们可以清楚地了解到,把IContainer当作是普通的widget来看待时,它和该container里有多少个widget并没有关系,并且也不是其中的任何一个widget。
注1:其实QueryInterface的意思就是object-oriented中的“is-a”的关系,即继承关系,而按照object-oriented的原则,is-a是比has-a强得多的关系,所以如果可能的话,推荐使用get,set函数来表达has-a的关系。
注2:其实普通的接口指针,如 IWidget * , IContainer * 等,都是指向虚函数表的2级指针。因为是2级指针,增加了相当的灵活性(还记得那著名的添加一个间接层的名言吗)。
5,Draw函数
当显示Container时,container会遍历所有的widget,并调用IWIDGET_Draw函数完成显示操作
Widget1
Container(wid2, wid3)
Widget3
IContainer( 0x11111111 )
IWidget( 0x22222222 )
三,Decorator的实现方法
1,说明
Decorator是一种特殊的container,它管理并且只管理一个widget。它向该widget添加更多的UI功能
2,结构体
struct WidgetContBase {
WidgetBase base;
IContainer container;
AEEVTBL(IContainer) vtContainer;
};
struct Decorator {
WidgetContBase base;
IWidget * pChild;
};
3,结构体说明
字段
说明
Base
说明该组件是一个普通的widget
container
IContainerVtbl *pvt ; 指向结构体的下一个字段vtContainer;就是通过这一个虚函数表,是该decorator可以被认为是一个container。当调用IDECORATOR_QueryInterface( IContainer )时,返回该指针的地址。
WidgetContBase * pMe ; 其实就是this指针
vtContainer
Container的虚函数表,通过该表,是widget(decorator)可以被认为是一个container。
pChild
被decorated的target widget。
摘抄的代码如下:
int WidgetContBase_QueryInterface(IWidget *po, AEECLSID clsid, void **ppo)
{
WidgetContBase *me = (WidgetContBase*) po;
if (clsid == AEEIID_CONTAINER) {
*ppo = (void *)&me->container;
WidgetBase_AddRef((IWidget*)po);
return SUCCESS;
}
return WidgetBase_QueryInterface(po, clsid, ppo);
}
可以看出:
IContainer本身是一个container,但是可以把它作为widget来看待。
IDecorator本身是一个widget,但是可以把它作为container来看待。
4,如果IDecorator已经wrap了target widget的话,那么调用ICONTAINER_GetWidget可以得到target widget。
IROOTCONTAINER_GetFirstWidget返回最先被加入的widget。
IROOTCONTAINER_GetLastWidget返回最后被加入的widget。