詳解Brew中Widget實(shí)現(xiàn)分析
Brew中Widget實(shí)現(xiàn)分析是本文要介紹的內(nèi)容,主要是來了解并學(xué)習(xí)Widget應(yīng)用的內(nèi)容,具體內(nèi)容的實(shí)現(xiàn)來看本文詳解。
一、WidgetBase及其作用
1、結(jié)構(gòu)體的定義
- 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、該結(jié)構(gòu)體定義了所有widget公用的數(shù)據(jù)成員。當(dāng)然也提供了公用的函數(shù),如WidgetBase_XXX等函數(shù)群。具體的widget 的實(shí)現(xiàn)類,都以該結(jié)構(gòu)體作為第一個(gè)成員。
二、ContainerBase及其作用
1、container的簡單說明
widget的容器,而container又可以看作是一種特殊的widget。這里就是一個(gè)composite模式。
2、WidgetNode
Container中的所有widget的相關(guān)信息放在一個(gè)雙向鏈表中。鏈表的節(jié)點(diǎn)的定義如下:
- 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構(gòu)成了雙向鏈表;piWidget就是容器中的一個(gè)widget的指針;rc代表了該widget的位置,及大小。
對容器的操作,如添加widget,刪除widget,查找widget,遍歷所有的widget等,都映射為對該鏈表的操作。
3、結(jié)構(gòu)體定義
- 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;
- }
- }
當(dāng)客戶通過該指針調(diào)用IWidget接口的方法時(shí),
- (*(IWidgetVtbl**)(void*)ptr)->AddRef();
*ptr為字段pvt的值,即指向IWidgetVtbl結(jié)構(gòu)體的指針。上述語句只不過是添加了強(qiáng)制類型轉(zhuǎn)換。
通過這里我們可以清楚地了解到,把IContainer當(dāng)作是普通的widget來看待時(shí),它和該container里有多少個(gè)widget并沒有關(guān)系,并且也不是其中的任何一個(gè)widget。
注1:其實(shí)QueryInterface的意思就是object-oriented中的“is-a”的關(guān)系,即繼承關(guān)系,而按照object-oriented的原則,is-a是比has-a強(qiáng)得多的關(guān)系,所以如果可能的話,推薦使用get,set函數(shù)來表達(dá)has-a的關(guān)系。
注2:其實(shí)普通的接口指針,如 IWidget * , IContainer * 等,都是指向虛函數(shù)表的2級指針。因?yàn)槭?級指針,增加了相當(dāng)?shù)撵`活性(還記得那著名的添加一個(gè)間接層的名言嗎)。
5、Draw函數(shù)
當(dāng)顯示Container時(shí),container會遍歷所有的widget,并調(diào)用IWIDGET_Draw函數(shù)完成顯示操作
- Widget1
- Container(wid2, wid3)
- Widget3
- Container( 0x11111111 )
- IWidget( 0x22222222 )
三、Decorator的實(shí)現(xiàn)方法
1、說明
Decorator是一種特殊的container,它管理并且只管理一個(gè)widget。它向該widget添加更多的UI功能
2、結(jié)構(gòu)體
- struct WidgetContBase {
- WidgetBase base;
- IContainer container;
- AEEVTBL(IContainer) vtContainer;
- };
- struct Decorator {
- WidgetContBase base;
- IWidget * pChild;
- };
3、結(jié)構(gòu)體說明
摘抄的代碼如下:
- 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本身是一個(gè)container,但是可以把它作為widget來看待。
IDecorator本身是一個(gè)widget,但是可以把它作為container來看待。
4、如果IDecorator已經(jīng)wrap了target widget的話,那么調(diào)用ICONTAINER_GetWidget可以得到target widget。
IROOTCONTAINER_GetFirstWidget返回最先被加入的widget。
IROOTCONTAINER_GetLastWidget返回最后被加入的widget。
小結(jié):詳解Brew中Widget實(shí)現(xiàn)分析的內(nèi)容介紹完了,希望通過Widget內(nèi)容的學(xué)習(xí)能對你有所幫助。