Brew中Widget实现分析是本文要介绍的内容,主要是来了解并学习Widget应用的内容,具体内容的实现来看本文详解。
一、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、各字段的说明
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、字段说明
摘抄的代码如下:
- 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
- Container( 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、结构体说明
摘抄的代码如下:
- 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。
小结:详解Brew中Widget实现分析的内容介绍完了,希望通过Widget内容的学习能对你有所帮助。