Home | History | Annotate | Download | only in core
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include <algorithm>
      8 
      9 #include "xfa/src/foxitlib.h"
     10 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
     11 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
     12 #include "xfa/src/fwl/src/core/include/fwl_threadimp.h"
     13 #include "xfa/src/fwl/src/core/include/fwl_appimp.h"
     14 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"
     15 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
     16 FWL_ERR IFWL_Widget::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
     17   return static_cast<CFWL_WidgetImp*>(GetImpl())
     18       ->GetWidgetRect(rect, bAutoSize);
     19 }
     20 FWL_ERR IFWL_Widget::GetGlobalRect(CFX_RectF& rect) {
     21   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetGlobalRect(rect);
     22 }
     23 FWL_ERR IFWL_Widget::SetWidgetRect(const CFX_RectF& rect) {
     24   return static_cast<CFWL_WidgetImp*>(GetImpl())->SetWidgetRect(rect);
     25 }
     26 FWL_ERR IFWL_Widget::GetClientRect(CFX_RectF& rect) {
     27   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetClientRect(rect);
     28 }
     29 IFWL_Widget* IFWL_Widget::GetParent() {
     30   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetParent();
     31 }
     32 FWL_ERR IFWL_Widget::SetParent(IFWL_Widget* pParent) {
     33   return static_cast<CFWL_WidgetImp*>(GetImpl())->SetParent(pParent);
     34 }
     35 IFWL_Widget* IFWL_Widget::GetOwner() {
     36   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetOwner();
     37 }
     38 FWL_ERR IFWL_Widget::SetOwner(IFWL_Widget* pOwner) {
     39   return static_cast<CFWL_WidgetImp*>(GetImpl())->SetOwner(pOwner);
     40 }
     41 IFWL_Widget* IFWL_Widget::GetOuter() {
     42   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetOuter();
     43 }
     44 FX_DWORD IFWL_Widget::GetStyles() {
     45   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetStyles();
     46 }
     47 FWL_ERR IFWL_Widget::ModifyStyles(FX_DWORD dwStylesAdded,
     48                                   FX_DWORD dwStylesRemoved) {
     49   return static_cast<CFWL_WidgetImp*>(GetImpl())
     50       ->ModifyStyles(dwStylesAdded, dwStylesRemoved);
     51 }
     52 FX_DWORD IFWL_Widget::GetStylesEx() {
     53   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetStylesEx();
     54 }
     55 FWL_ERR IFWL_Widget::ModifyStylesEx(FX_DWORD dwStylesExAdded,
     56                                     FX_DWORD dwStylesExRemoved) {
     57   return static_cast<CFWL_WidgetImp*>(GetImpl())
     58       ->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
     59 }
     60 FX_DWORD IFWL_Widget::GetStates() {
     61   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetStates();
     62 }
     63 FWL_ERR IFWL_Widget::SetStates(FX_DWORD dwStates, FX_BOOL bSet) {
     64   return static_cast<CFWL_WidgetImp*>(GetImpl())->SetStates(dwStates, bSet);
     65 }
     66 FWL_ERR IFWL_Widget::SetPrivateData(void* module_id,
     67                                     void* pData,
     68                                     PD_CALLBACK_FREEDATA callback) {
     69   return static_cast<CFWL_WidgetImp*>(GetImpl())
     70       ->SetPrivateData(module_id, pData, callback);
     71 }
     72 void* IFWL_Widget::GetPrivateData(void* module_id) {
     73   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetPrivateData(module_id);
     74 }
     75 FWL_ERR IFWL_Widget::Update() {
     76   return static_cast<CFWL_WidgetImp*>(GetImpl())->Update();
     77 }
     78 FWL_ERR IFWL_Widget::LockUpdate() {
     79   return static_cast<CFWL_WidgetImp*>(GetImpl())->LockUpdate();
     80 }
     81 FWL_ERR IFWL_Widget::UnlockUpdate() {
     82   return static_cast<CFWL_WidgetImp*>(GetImpl())->UnlockUpdate();
     83 }
     84 FX_DWORD IFWL_Widget::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
     85   return static_cast<CFWL_WidgetImp*>(GetImpl())->HitTest(fx, fy);
     86 }
     87 FWL_ERR IFWL_Widget::TransformTo(IFWL_Widget* pWidget,
     88                                  FX_FLOAT& fx,
     89                                  FX_FLOAT& fy) {
     90   return static_cast<CFWL_WidgetImp*>(GetImpl())->TransformTo(pWidget, fx, fy);
     91 }
     92 FWL_ERR IFWL_Widget::TransformTo(IFWL_Widget* pWidget, CFX_RectF& rt) {
     93   return static_cast<CFWL_WidgetImp*>(GetImpl())->TransformTo(pWidget, rt);
     94 }
     95 FWL_ERR IFWL_Widget::GetMatrix(CFX_Matrix& matrix, FX_BOOL bGlobal) {
     96   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetMatrix(matrix, bGlobal);
     97 }
     98 FWL_ERR IFWL_Widget::SetMatrix(const CFX_Matrix& matrix) {
     99   return static_cast<CFWL_WidgetImp*>(GetImpl())->SetMatrix(matrix);
    100 }
    101 FWL_ERR IFWL_Widget::DrawWidget(CFX_Graphics* pGraphics,
    102                                 const CFX_Matrix* pMatrix) {
    103   return static_cast<CFWL_WidgetImp*>(GetImpl())
    104       ->DrawWidget(pGraphics, pMatrix);
    105 }
    106 IFWL_ThemeProvider* IFWL_Widget::GetThemeProvider() {
    107   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetThemeProvider();
    108 }
    109 FWL_ERR IFWL_Widget::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
    110   return static_cast<CFWL_WidgetImp*>(GetImpl())
    111       ->SetThemeProvider(pThemeProvider);
    112 }
    113 FWL_ERR IFWL_Widget::SetDataProvider(IFWL_DataProvider* pDataProvider) {
    114   return static_cast<CFWL_WidgetImp*>(GetImpl())
    115       ->SetDataProvider(pDataProvider);
    116 }
    117 IFWL_WidgetDelegate* IFWL_Widget::SetDelegate(IFWL_WidgetDelegate* pDelegate) {
    118   return static_cast<CFWL_WidgetImp*>(GetImpl())->SetDelegate(pDelegate);
    119 }
    120 IFWL_NoteThread* IFWL_Widget::GetOwnerThread() const {
    121   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetOwnerThread();
    122 }
    123 CFX_SizeF IFWL_Widget::GetOffsetFromParent(IFWL_Widget* pParent) {
    124   return static_cast<CFWL_WidgetImp*>(GetImpl())->GetOffsetFromParent(pParent);
    125 }
    126 FWL_ERR CFWL_WidgetImp::Initialize() {
    127   IFWL_App* pApp = FWL_GetApp();
    128   if (!pApp)
    129     return FWL_ERR_Indefinite;
    130   IFWL_AdapterNative* pAdapter = pApp->GetAdapterNative();
    131   if (!pAdapter)
    132     return FWL_ERR_Indefinite;
    133   IFWL_AdapterThreadMgr* pAdapterThread = pAdapter->GetThreadMgr();
    134   if (!pAdapterThread)
    135     return FWL_ERR_Indefinite;
    136   SetOwnerThread(static_cast<CFWL_NoteThreadImp*>(
    137       pAdapterThread->GetCurrentThread()->GetImpl()));
    138   IFWL_Widget* pParent = m_pProperties->m_pParent;
    139   m_pWidgetMgr->InsertWidget(pParent, m_pInterface);
    140   if (!IsChild()) {
    141     {
    142       IFWL_Widget* pOwner = m_pProperties->m_pOwner;
    143       if (pOwner) {
    144         m_pWidgetMgr->SetOwner(pOwner, m_pInterface);
    145       }
    146     }
    147     m_pWidgetMgr->CreateWidget_Native(m_pInterface);
    148   }
    149   return FWL_ERR_Succeeded;
    150 }
    151 FWL_ERR CFWL_WidgetImp::Finalize() {
    152   NotifyDriver();
    153   IFWL_Form* pForm = static_cast<IFWL_Form*>(
    154       FWL_GetWidgetMgr()->GetWidget(m_pInterface, FWL_WGTRELATION_SystemForm));
    155   if (pForm && pForm != m_pInterface) {
    156     IFWL_Content* pContent = pForm->GetContent();
    157     if (pContent) {
    158       pContent->RemoveWidget(m_pInterface);
    159     }
    160   }
    161   if (!IsChild()) {
    162     m_pWidgetMgr->DestroyWidget_Native(m_pInterface);
    163   }
    164   m_pWidgetMgr->RemoveWidget(m_pInterface);
    165   return FWL_ERR_Succeeded;
    166 }
    167 FWL_ERR CFWL_WidgetImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
    168   if (bAutoSize) {
    169     if (HasEdge()) {
    170       FX_FLOAT fEdge = GetEdgeWidth();
    171       rect.Inflate(fEdge, fEdge);
    172     }
    173     if (HasBorder()) {
    174       FX_FLOAT fBorder = GetBorderSize();
    175       rect.Inflate(fBorder, fBorder);
    176     }
    177   } else {
    178     rect = m_pProperties->m_rtWidget;
    179   }
    180   return FWL_ERR_Succeeded;
    181 }
    182 FWL_ERR CFWL_WidgetImp::GetGlobalRect(CFX_RectF& rect) {
    183   IFWL_Widget* pForm =
    184       m_pWidgetMgr->GetWidget(m_pInterface, FWL_WGTRELATION_SystemForm);
    185   if (!pForm)
    186     return FWL_ERR_Indefinite;
    187   rect.Set(0, 0, m_pProperties->m_rtWidget.width,
    188            m_pProperties->m_rtWidget.height);
    189   if (pForm == m_pInterface) {
    190     return FWL_ERR_Succeeded;
    191   }
    192   return TransformTo(pForm, rect);
    193 }
    194 FWL_ERR CFWL_WidgetImp::SetWidgetRect(const CFX_RectF& rect) {
    195   CFX_RectF rtOld = m_pProperties->m_rtWidget;
    196   m_pProperties->m_rtWidget = rect;
    197   if (IsChild()) {
    198     if (FXSYS_fabs(rtOld.width - rect.width) > 0.5f ||
    199         FXSYS_fabs(rtOld.height - rect.height) > 0.5f) {
    200       CFWL_EvtSizeChanged ev;
    201       ev.m_pSrcTarget = m_pInterface;
    202       ev.m_rtOld = rtOld;
    203       ev.m_rtNew = rect;
    204       IFWL_WidgetDelegate* pDelegate = SetDelegate(NULL);
    205       if (pDelegate) {
    206         pDelegate->OnProcessEvent(&ev);
    207       }
    208     }
    209     return FWL_ERR_Succeeded;
    210   }
    211   m_pWidgetMgr->SetWidgetRect_Native(m_pInterface, rect);
    212   return FWL_ERR_Succeeded;
    213 }
    214 FWL_ERR CFWL_WidgetImp::GetClientRect(CFX_RectF& rect) {
    215   GetEdgeRect(rect);
    216   if (HasEdge()) {
    217     FX_FLOAT fEdge = GetEdgeWidth();
    218     rect.Deflate(fEdge, fEdge);
    219   }
    220   return FWL_ERR_Succeeded;
    221 }
    222 IFWL_Widget* CFWL_WidgetImp::GetParent() {
    223   return m_pWidgetMgr->GetWidget(m_pInterface, FWL_WGTRELATION_Parent);
    224 }
    225 FWL_ERR CFWL_WidgetImp::SetParent(IFWL_Widget* pParent) {
    226   m_pProperties->m_pParent = pParent;
    227   m_pWidgetMgr->SetParent(pParent, m_pInterface);
    228   return FWL_ERR_Succeeded;
    229 }
    230 IFWL_Widget* CFWL_WidgetImp::GetOwner() {
    231   return m_pWidgetMgr->GetWidget(m_pInterface, FWL_WGTRELATION_Owner);
    232 }
    233 FWL_ERR CFWL_WidgetImp::SetOwner(IFWL_Widget* pOwner) {
    234   m_pProperties->m_pOwner = pOwner;
    235   m_pWidgetMgr->SetOwner(pOwner, m_pInterface);
    236   return FWL_ERR_Succeeded;
    237 }
    238 IFWL_Widget* CFWL_WidgetImp::GetOuter() {
    239   return m_pOuter;
    240 }
    241 FX_DWORD CFWL_WidgetImp::GetStyles() {
    242   return m_pProperties->m_dwStyles;
    243 }
    244 FWL_ERR CFWL_WidgetImp::ModifyStyles(FX_DWORD dwStylesAdded,
    245                                      FX_DWORD dwStylesRemoved) {
    246   m_pProperties->m_dwStyles =
    247       (m_pProperties->m_dwStyles & ~dwStylesRemoved) | dwStylesAdded;
    248   return FWL_ERR_Succeeded;
    249 }
    250 FX_DWORD CFWL_WidgetImp::GetStylesEx() {
    251   return m_pProperties->m_dwStyleExes;
    252 }
    253 FWL_ERR CFWL_WidgetImp::ModifyStylesEx(FX_DWORD dwStylesExAdded,
    254                                        FX_DWORD dwStylesExRemoved) {
    255   m_pProperties->m_dwStyleExes =
    256       (m_pProperties->m_dwStyleExes & ~dwStylesExRemoved) | dwStylesExAdded;
    257   return FWL_ERR_Succeeded;
    258 }
    259 FX_DWORD CFWL_WidgetImp::GetStates() {
    260   return m_pProperties->m_dwStates;
    261 }
    262 static void NotifyHideChildWidget(IFWL_WidgetMgr* widgetMgr,
    263                                   IFWL_Widget* widget,
    264                                   CFWL_NoteDriver* noteDriver) {
    265   IFWL_Widget* child = widgetMgr->GetWidget(widget, FWL_WGTRELATION_FirstChild);
    266   while (child) {
    267     noteDriver->NotifyTargetHide(child);
    268     NotifyHideChildWidget(widgetMgr, child, noteDriver);
    269     child = widgetMgr->GetWidget(child, FWL_WGTRELATION_NextSibling);
    270   }
    271 }
    272 FWL_ERR CFWL_WidgetImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) {
    273   bSet ? (m_pProperties->m_dwStates |= dwStates)
    274        : (m_pProperties->m_dwStates &= ~dwStates);
    275   FWL_ERR ret = FWL_ERR_Succeeded;
    276   if (dwStates & FWL_WGTSTATE_Invisible) {
    277     if (bSet) {
    278       ret = m_pWidgetMgr->HideWidget_Native(m_pInterface);
    279       CFWL_NoteDriver* noteDriver =
    280           static_cast<CFWL_NoteDriver*>(GetOwnerThread()->GetNoteDriver());
    281       IFWL_WidgetMgr* widgetMgr = FWL_GetWidgetMgr();
    282       noteDriver->NotifyTargetHide(m_pInterface);
    283       IFWL_Widget* child =
    284           widgetMgr->GetWidget(m_pInterface, FWL_WGTRELATION_FirstChild);
    285       while (child) {
    286         noteDriver->NotifyTargetHide(child);
    287         NotifyHideChildWidget(widgetMgr, child, noteDriver);
    288         child = widgetMgr->GetWidget(child, FWL_WGTRELATION_NextSibling);
    289       }
    290     } else {
    291       ret = m_pWidgetMgr->ShowWidget_Native(m_pInterface);
    292     }
    293   }
    294   return ret;
    295 }
    296 FWL_ERR CFWL_WidgetImp::SetPrivateData(void* module_id,
    297                                        void* pData,
    298                                        PD_CALLBACK_FREEDATA callback) {
    299   if (!m_pPrivateData) {
    300     m_pPrivateData = new CFX_PrivateData;
    301   }
    302   m_pPrivateData->SetPrivateData(module_id, pData, callback);
    303   return FWL_ERR_Succeeded;
    304 }
    305 void* CFWL_WidgetImp::GetPrivateData(void* module_id) {
    306   if (!m_pPrivateData)
    307     return NULL;
    308   return m_pPrivateData->GetPrivateData(module_id);
    309 }
    310 FWL_ERR CFWL_WidgetImp::Update() {
    311   return FWL_ERR_Succeeded;
    312 }
    313 FWL_ERR CFWL_WidgetImp::LockUpdate() {
    314   m_iLock++;
    315   return FWL_ERR_Succeeded;
    316 }
    317 FWL_ERR CFWL_WidgetImp::UnlockUpdate() {
    318   if (IsLocked()) {
    319     m_iLock--;
    320   }
    321   return FWL_ERR_Succeeded;
    322 }
    323 FX_DWORD CFWL_WidgetImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
    324   CFX_RectF rtClient;
    325   GetClientRect(rtClient);
    326   if (rtClient.Contains(fx, fy)) {
    327     return FWL_WGTHITTEST_Client;
    328   }
    329   if (HasEdge()) {
    330     CFX_RectF rtEdge;
    331     GetEdgeRect(rtEdge);
    332     if (rtEdge.Contains(fx, fy)) {
    333       return FWL_WGTHITTEST_Edge;
    334     }
    335   }
    336   if (HasBorder()) {
    337     CFX_RectF rtRelative;
    338     GetRelativeRect(rtRelative);
    339     if (rtRelative.Contains(fx, fy)) {
    340       return FWL_WGTHITTEST_Border;
    341     }
    342   }
    343   return FWL_WGTHITTEST_Unknown;
    344 }
    345 FWL_ERR CFWL_WidgetImp::TransformTo(IFWL_Widget* pWidget,
    346                                     FX_FLOAT& fx,
    347                                     FX_FLOAT& fy) {
    348   if (m_pWidgetMgr->IsFormDisabled()) {
    349     CFX_SizeF szOffset;
    350     if (IsParent(pWidget)) {
    351       szOffset = GetOffsetFromParent(pWidget);
    352     } else {
    353       szOffset = pWidget->GetOffsetFromParent(m_pInterface);
    354       szOffset.x = -szOffset.x;
    355       szOffset.y = -szOffset.y;
    356     }
    357     fx += szOffset.x;
    358     fy += szOffset.y;
    359     return FWL_ERR_Succeeded;
    360   }
    361   CFX_RectF r;
    362   CFX_Matrix m;
    363   IFWL_Widget* parent = GetParent();
    364   if (parent) {
    365     GetWidgetRect(r);
    366     fx += r.left;
    367     fy += r.top;
    368     GetMatrix(m, TRUE);
    369     m.TransformPoint(fx, fy);
    370   }
    371   IFWL_Widget* form1 =
    372       m_pWidgetMgr->GetWidget(m_pInterface, FWL_WGTRELATION_SystemForm);
    373   if (!form1)
    374     return FWL_ERR_Indefinite;
    375   if (!pWidget) {
    376     form1->GetWidgetRect(r);
    377     fx += r.left;
    378     fy += r.top;
    379 #ifdef FWL_UseMacSystemBorder
    380     if (form1->GetStyles() & FWL_WGTSTYLE_Caption) {
    381       FX_FLOAT l, t, r, b;
    382       l = t = r = b = 0;
    383       FWL_GetAdapterWidgetMgr()->GetSystemBorder(l, t, r, b);
    384       fy += t;
    385     }
    386 #endif
    387     return FWL_ERR_Succeeded;
    388   }
    389   IFWL_Widget* form2 =
    390       m_pWidgetMgr->GetWidget(pWidget, FWL_WGTRELATION_SystemForm);
    391   if (!form2)
    392     return FWL_ERR_Indefinite;
    393   if (form1 != form2) {
    394     form1->GetWidgetRect(r);
    395     fx += r.left;
    396     fy += r.top;
    397     form2->GetWidgetRect(r);
    398     fx -= r.left;
    399     fy -= r.top;
    400 #ifdef FWL_UseMacSystemBorder
    401     if ((form1->GetStyles() & FWL_WGTSTYLE_Caption) !=
    402         (form2->GetStyles() & FWL_WGTSTYLE_Caption)) {
    403       FX_FLOAT l, t, r, b;
    404       l = t = r = b = 0;
    405       FWL_GetAdapterWidgetMgr()->GetSystemBorder(l, t, r, b);
    406       (form1->GetStyles() & FWL_WGTSTYLE_Caption) ? (fy += t) : (fy -= t);
    407     }
    408 #endif
    409   }
    410   parent = pWidget->GetParent();
    411   if (parent) {
    412     pWidget->GetMatrix(m, TRUE);
    413     CFX_Matrix m1;
    414     m1.SetIdentity();
    415     m1.SetReverse(m);
    416     m1.TransformPoint(fx, fy);
    417     pWidget->GetWidgetRect(r);
    418     fx -= r.left;
    419     fy -= r.top;
    420   }
    421   return FWL_ERR_Succeeded;
    422 }
    423 FWL_ERR CFWL_WidgetImp::TransformTo(IFWL_Widget* pWidget, CFX_RectF& rt) {
    424   return TransformTo(pWidget, rt.left, rt.top);
    425 }
    426 FWL_ERR CFWL_WidgetImp::GetMatrix(CFX_Matrix& matrix, FX_BOOL bGlobal) {
    427   if (!m_pProperties)
    428     return FWL_ERR_Indefinite;
    429   if (bGlobal) {
    430     IFWL_Widget* parent = GetParent();
    431     CFX_PtrArray parents;
    432     while (parent) {
    433       parents.Add(parent);
    434       parent = parent->GetParent();
    435     }
    436     matrix.SetIdentity();
    437     CFX_Matrix ctmOnParent;
    438     CFX_RectF rect;
    439     int32_t count = parents.GetSize();
    440     for (int32_t i = count - 2; i >= 0; i--) {
    441       parent = static_cast<IFWL_Widget*>(parents.GetAt(i));
    442       parent->GetMatrix(ctmOnParent, FALSE);
    443       parent->GetWidgetRect(rect);
    444       matrix.Concat(ctmOnParent, TRUE);
    445       matrix.Translate(rect.left, rect.top, TRUE);
    446     }
    447     matrix.Concat(m_pProperties->m_ctmOnParent, TRUE);
    448     parents.RemoveAll();
    449   } else {
    450     matrix = m_pProperties->m_ctmOnParent;
    451   }
    452   return FWL_ERR_Succeeded;
    453 }
    454 FWL_ERR CFWL_WidgetImp::SetMatrix(const CFX_Matrix& matrix) {
    455   if (!m_pProperties)
    456     return FWL_ERR_Indefinite;
    457   IFWL_Widget* parent = GetParent();
    458   if (!parent) {
    459     return FWL_ERR_Indefinite;
    460   }
    461   m_pProperties->m_ctmOnParent = matrix;
    462   return FWL_ERR_Succeeded;
    463 }
    464 FWL_ERR CFWL_WidgetImp::DrawWidget(CFX_Graphics* pGraphics,
    465                                    const CFX_Matrix* pMatrix) {
    466   return FWL_ERR_Indefinite;
    467 }
    468 IFWL_ThemeProvider* CFWL_WidgetImp::GetThemeProvider() {
    469   return m_pProperties->m_pThemeProvider;
    470 }
    471 FWL_ERR CFWL_WidgetImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
    472   m_pProperties->m_pThemeProvider = pThemeProvider;
    473   return FWL_ERR_Succeeded;
    474 }
    475 FWL_ERR CFWL_WidgetImp::SetDataProvider(IFWL_DataProvider* pDataProvider) {
    476   m_pProperties->m_pDataProvider = pDataProvider;
    477   return FWL_ERR_Succeeded;
    478 }
    479 IFWL_WidgetDelegate* CFWL_WidgetImp::SetDelegate(
    480     IFWL_WidgetDelegate* pDelegate) {
    481   if (!m_pCurDelegate) {
    482     m_pCurDelegate = m_pDelegate;
    483   }
    484   if (!pDelegate) {
    485     return m_pCurDelegate;
    486   }
    487   IFWL_WidgetDelegate* pOldDelegate = m_pCurDelegate;
    488   m_pCurDelegate = pDelegate;
    489   return pOldDelegate;
    490 }
    491 IFWL_NoteThread* CFWL_WidgetImp::GetOwnerThread() const {
    492   return static_cast<IFWL_NoteThread*>(m_pOwnerThread->GetInterface());
    493 }
    494 FWL_ERR CFWL_WidgetImp::SetOwnerThread(CFWL_NoteThreadImp* pOwnerThread) {
    495   m_pOwnerThread = pOwnerThread;
    496   return FWL_ERR_Succeeded;
    497 }
    498 IFWL_Widget* CFWL_WidgetImp::GetInterface() const {
    499   return m_pInterface;
    500 }
    501 void CFWL_WidgetImp::SetInterface(IFWL_Widget* pInterface) {
    502   m_pInterface = pInterface;
    503 }
    504 CFWL_WidgetImp::CFWL_WidgetImp(const CFWL_WidgetImpProperties& properties,
    505                                IFWL_Widget* pOuter)
    506     : m_pProperties(new CFWL_WidgetImpProperties),
    507       m_pPrivateData(NULL),
    508       m_pDelegate(NULL),
    509       m_pCurDelegate(NULL),
    510       m_pOuter(pOuter),
    511       m_pInterface(NULL),
    512       m_iLock(0) {
    513   *m_pProperties = properties;
    514   m_pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    515   FXSYS_assert(m_pWidgetMgr != NULL);
    516 }
    517 CFWL_WidgetImp::~CFWL_WidgetImp() {
    518   if (m_pPrivateData) {
    519     delete m_pPrivateData;
    520     m_pPrivateData = NULL;
    521   }
    522   if (m_pProperties) {
    523     delete m_pProperties;
    524     m_pProperties = NULL;
    525   }
    526 }
    527 FX_BOOL CFWL_WidgetImp::IsEnabled() const {
    528   return (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 0;
    529 }
    530 FX_BOOL CFWL_WidgetImp::IsVisible() const {
    531   return (m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) == 0;
    532 }
    533 FX_BOOL CFWL_WidgetImp::IsActive() const {
    534   return (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) == 0;
    535 }
    536 FX_BOOL CFWL_WidgetImp::IsOverLapper() const {
    537   return (m_pProperties->m_dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
    538          FWL_WGTSTYLE_OverLapper;
    539 }
    540 FX_BOOL CFWL_WidgetImp::IsPopup() const {
    541   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Popup);
    542 }
    543 FX_BOOL CFWL_WidgetImp::IsChild() const {
    544   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Child);
    545 }
    546 FX_BOOL CFWL_WidgetImp::IsLocked() const {
    547   return m_iLock > 0;
    548 }
    549 FX_BOOL CFWL_WidgetImp::IsOffscreen() const {
    550   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Offscreen);
    551 }
    552 FX_BOOL CFWL_WidgetImp::HasBorder() const {
    553   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border);
    554 }
    555 FX_BOOL CFWL_WidgetImp::HasEdge() const {
    556   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_EdgeMask);
    557 }
    558 void CFWL_WidgetImp::GetEdgeRect(CFX_RectF& rtEdge) {
    559   rtEdge = m_pProperties->m_rtWidget;
    560   rtEdge.left = rtEdge.top = 0;
    561   if (HasBorder()) {
    562     FX_FLOAT fCX = GetBorderSize();
    563     FX_FLOAT fCY = GetBorderSize(FALSE);
    564     rtEdge.Deflate(fCX, fCY);
    565   }
    566 }
    567 FX_FLOAT CFWL_WidgetImp::GetBorderSize(FX_BOOL bCX) {
    568   FX_FLOAT* pfBorder = static_cast<FX_FLOAT*>(GetThemeCapacity(
    569       bCX ? FWL_WGTCAPACITY_CXBorder : FWL_WGTCAPACITY_CYBorder));
    570   if (!pfBorder)
    571     return 0;
    572   return *pfBorder;
    573 }
    574 FX_FLOAT CFWL_WidgetImp::GetEdgeWidth() {
    575   FX_DWORD dwCapacity = 0;
    576   switch (m_pProperties->m_dwStyles & FWL_WGTSTYLE_EdgeMask) {
    577     case FWL_WGTSTYLE_EdgeFlat: {
    578       dwCapacity = FWL_WGTCAPACITY_EdgeFlat;
    579       break;
    580     }
    581     case FWL_WGTSTYLE_EdgeRaised: {
    582       dwCapacity = FWL_WGTCAPACITY_EdgeRaised;
    583       break;
    584     }
    585     case FWL_WGTSTYLE_EdgeSunken: {
    586       dwCapacity = FWL_WGTCAPACITY_EdgeSunken;
    587       break;
    588     }
    589   }
    590   if (dwCapacity > 0) {
    591     FX_FLOAT* fRet = static_cast<FX_FLOAT*>(GetThemeCapacity(dwCapacity));
    592     return fRet ? *fRet : 0;
    593   }
    594   return 0;
    595 }
    596 void CFWL_WidgetImp::GetRelativeRect(CFX_RectF& rect) {
    597   rect = m_pProperties->m_rtWidget;
    598   rect.left = rect.top = 0;
    599 }
    600 void* CFWL_WidgetImp::GetThemeCapacity(FX_DWORD dwCapacity) {
    601   IFWL_ThemeProvider* pTheme = GetAvailableTheme();
    602   if (!pTheme)
    603     return NULL;
    604   CFWL_ThemePart part;
    605   part.m_pWidget = m_pInterface;
    606   return pTheme->GetCapacity(&part, dwCapacity);
    607 }
    608 IFWL_ThemeProvider* CFWL_WidgetImp::GetAvailableTheme() {
    609   if (m_pProperties->m_pThemeProvider) {
    610     return m_pProperties->m_pThemeProvider;
    611   }
    612   IFWL_Widget* pUp = m_pInterface;
    613   do {
    614     FWL_WGTRELATION relation = (pUp->GetStyles() & FWL_WGTSTYLE_Popup)
    615                                    ? FWL_WGTRELATION_Owner
    616                                    : FWL_WGTRELATION_Parent;
    617     pUp = m_pWidgetMgr->GetWidget(pUp, relation);
    618     if (pUp) {
    619       IFWL_ThemeProvider* pRet = pUp->GetThemeProvider();
    620       if (pRet && pRet->IsValidWidget(m_pInterface)) {
    621         return pRet;
    622       }
    623     }
    624   } while (pUp);
    625   return FWL_GetApp()->GetThemeProvider();
    626 }
    627 CFWL_WidgetImp* CFWL_WidgetImp::GetRootOuter() {
    628   IFWL_Widget* pRet = m_pOuter;
    629   if (!pRet)
    630     return nullptr;
    631   while (IFWL_Widget* pOuter = pRet->GetOuter()) {
    632     pRet = pOuter;
    633   }
    634   return static_cast<CFWL_WidgetImp*>(pRet->GetImpl());
    635 }
    636 #define FWL_WGT_CalcHeight 2048
    637 #define FWL_WGT_CalcWidth 2048
    638 #define FWL_WGT_CalcMultiLineDefWidth 120.0f
    639 CFX_SizeF CFWL_WidgetImp::CalcTextSize(const CFX_WideString& wsText,
    640                                        IFWL_ThemeProvider* pTheme,
    641                                        FX_BOOL bMultiLine,
    642                                        int32_t iLineWidth) {
    643   CFX_SizeF sz;
    644   sz.Set(0, 0);
    645   if (!pTheme)
    646     return sz;
    647   CFWL_ThemeText calPart;
    648   calPart.m_pWidget = m_pInterface;
    649   calPart.m_wsText = wsText;
    650   calPart.m_dwTTOStyles =
    651       bMultiLine ? FDE_TTOSTYLE_LineWrap : FDE_TTOSTYLE_SingleLine;
    652   calPart.m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
    653   CFX_RectF rect;
    654   FX_FLOAT fWidth = bMultiLine
    655                         ? (iLineWidth > 0 ? (FX_FLOAT)iLineWidth
    656                                           : FWL_WGT_CalcMultiLineDefWidth)
    657                         : FWL_WGT_CalcWidth;
    658   rect.Set(0, 0, fWidth, FWL_WGT_CalcHeight);
    659   pTheme->CalcTextRect(&calPart, rect);
    660   sz.x = rect.width;
    661   sz.y = rect.height;
    662   return sz;
    663 }
    664 void CFWL_WidgetImp::CalcTextRect(const CFX_WideString& wsText,
    665                                   IFWL_ThemeProvider* pTheme,
    666                                   FX_DWORD dwTTOStyles,
    667                                   int32_t iTTOAlign,
    668                                   CFX_RectF& rect) {
    669   CFWL_ThemeText calPart;
    670   calPart.m_pWidget = m_pInterface;
    671   calPart.m_wsText = wsText;
    672   calPart.m_dwTTOStyles = dwTTOStyles;
    673   calPart.m_iTTOAlign = iTTOAlign;
    674   pTheme->CalcTextRect(&calPart, rect);
    675 }
    676 void CFWL_WidgetImp::SetFocus(FX_BOOL bFocus) {
    677   if (m_pWidgetMgr->IsFormDisabled())
    678     return;
    679   IFWL_NoteThread* pThread = GetOwnerThread();
    680   if (!pThread)
    681     return;
    682   CFWL_NoteDriver* pDriver =
    683       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    684   if (!pDriver)
    685     return;
    686   IFWL_Widget* curFocus = pDriver->GetFocus();
    687   if (bFocus && curFocus != m_pInterface) {
    688     pDriver->SetFocus(m_pInterface);
    689   } else if (!bFocus && curFocus == m_pInterface) {
    690     pDriver->SetFocus(NULL);
    691   }
    692 }
    693 void CFWL_WidgetImp::SetGrab(FX_BOOL bSet) {
    694   IFWL_NoteThread* pThread = GetOwnerThread();
    695   if (!pThread)
    696     return;
    697   CFWL_NoteDriver* pDriver =
    698       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    699   pDriver->SetGrab(m_pInterface, bSet);
    700 }
    701 FX_BOOL CFWL_WidgetImp::GetPopupPos(FX_FLOAT fMinHeight,
    702                                     FX_FLOAT fMaxHeight,
    703                                     const CFX_RectF& rtAnchor,
    704                                     CFX_RectF& rtPopup) {
    705   if (GetClassID() == FWL_CLASSHASH_Menu) {
    706     return GetPopupPosMenu(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
    707   } else {
    708     if (GetClassID() == FWL_CLASSHASH_ComboBox) {
    709       if (m_pWidgetMgr->IsFormDisabled()) {
    710         return m_pWidgetMgr->GetAdapterPopupPos(m_pInterface, fMinHeight,
    711                                                 fMaxHeight, rtAnchor, rtPopup);
    712       } else {
    713         return GetPopupPosComboBox(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
    714       }
    715     } else if (GetClassID() == FWL_CLASSHASH_DateTimePicker &&
    716                m_pWidgetMgr->IsFormDisabled()) {
    717       return m_pWidgetMgr->GetAdapterPopupPos(m_pInterface, fMinHeight,
    718                                               fMaxHeight, rtAnchor, rtPopup);
    719     } else {
    720       return GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
    721     }
    722   }
    723   return FALSE;
    724 }
    725 FX_BOOL CFWL_WidgetImp::GetPopupPosMenu(FX_FLOAT fMinHeight,
    726                                         FX_FLOAT fMaxHeight,
    727                                         const CFX_RectF& rtAnchor,
    728                                         CFX_RectF& rtPopup) {
    729   FX_FLOAT fx = 0;
    730   FX_FLOAT fy = 0;
    731   FX_FLOAT fScreenWidth = 0;
    732   FX_FLOAT fScreenHeight = 0;
    733   GetScreenSize(fScreenWidth, fScreenHeight);
    734   if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) {
    735     FX_BOOL bLeft = m_pProperties->m_rtWidget.left < 0;
    736     FX_FLOAT fRight = rtAnchor.right() + rtPopup.width;
    737     TransformTo(NULL, fx, fy);
    738     if (fRight + fx > fScreenWidth || bLeft) {
    739       rtPopup.Set(rtAnchor.left - rtPopup.width, rtAnchor.top, rtPopup.width,
    740                   rtPopup.height);
    741     } else {
    742       rtPopup.Set(rtAnchor.right(), rtAnchor.top, rtPopup.width,
    743                   rtPopup.height);
    744     }
    745   } else {
    746     FX_FLOAT fBottom = rtAnchor.bottom() + rtPopup.height;
    747     TransformTo(NULL, fx, fy);
    748     if (fBottom + fy > fScreenHeight) {
    749       rtPopup.Set(rtAnchor.left, rtAnchor.top - rtPopup.height, rtPopup.width,
    750                   rtPopup.height);
    751     } else {
    752       rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
    753                   rtPopup.height);
    754     }
    755   }
    756   rtPopup.Offset(fx, fy);
    757   return TRUE;
    758 }
    759 FX_BOOL CFWL_WidgetImp::GetPopupPosComboBox(FX_FLOAT fMinHeight,
    760                                             FX_FLOAT fMaxHeight,
    761                                             const CFX_RectF& rtAnchor,
    762                                             CFX_RectF& rtPopup) {
    763   FX_FLOAT fx = 0;
    764   FX_FLOAT fy = 0;
    765   FX_FLOAT fScreenWidth = 0;
    766   FX_FLOAT fScreenHeight = 0;
    767   GetScreenSize(fScreenWidth, fScreenHeight);
    768   FX_FLOAT fPopHeight = rtPopup.height;
    769   if (rtPopup.height > fMaxHeight) {
    770     fPopHeight = fMaxHeight;
    771   } else if (rtPopup.height < fMinHeight) {
    772     fPopHeight = fMinHeight;
    773   }
    774   FX_FLOAT fWidth = std::max(rtAnchor.width, rtPopup.width);
    775   FX_FLOAT fBottom = rtAnchor.bottom() + fPopHeight;
    776   TransformTo(NULL, fx, fy);
    777   if (fBottom + fy > fScreenHeight) {
    778     rtPopup.Set(rtAnchor.left, rtAnchor.top - fPopHeight, fWidth, fPopHeight);
    779   } else {
    780     rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), fWidth, fPopHeight);
    781   }
    782   rtPopup.Offset(fx, fy);
    783   return TRUE;
    784 }
    785 FX_BOOL CFWL_WidgetImp::GetPopupPosGeneral(FX_FLOAT fMinHeight,
    786                                            FX_FLOAT fMaxHeight,
    787                                            const CFX_RectF& rtAnchor,
    788                                            CFX_RectF& rtPopup) {
    789   FX_FLOAT fx = 0;
    790   FX_FLOAT fy = 0;
    791   FX_FLOAT fScreenWidth = 0;
    792   FX_FLOAT fScreenHeight = 0;
    793   GetScreenSize(fScreenWidth, fScreenHeight);
    794   TransformTo(NULL, fx, fy);
    795   if (rtAnchor.bottom() + fy > fScreenHeight) {
    796     rtPopup.Set(rtAnchor.left, rtAnchor.top - rtPopup.height, rtPopup.width,
    797                 rtPopup.height);
    798   } else {
    799     rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
    800                 rtPopup.height);
    801   }
    802   rtPopup.Offset(fx, fy);
    803   return TRUE;
    804 }
    805 FX_BOOL CFWL_WidgetImp::GetScreenSize(FX_FLOAT& fx, FX_FLOAT& fy) {
    806   IFWL_AdapterNative* pNative = FWL_GetAdapterNative();
    807   IFWL_AdapterMonitorMgr* pMonitorMgr = pNative->GetMonitorMgr();
    808   if (!pMonitorMgr)
    809     return FALSE;
    810   FWL_HMONITOR hMonitor = pMonitorMgr->GetMonitorByPoint(fx, fy);
    811   pMonitorMgr->GetMonitorSize(hMonitor, fx, fy);
    812   return TRUE;
    813 }
    814 void CFWL_WidgetImp::RegisterEventTarget(IFWL_Widget* pEventSource,
    815                                          FX_DWORD dwFilter) {
    816   IFWL_NoteThread* pThread = GetOwnerThread();
    817   if (!pThread)
    818     return;
    819   IFWL_NoteDriver* pNoteDriver = pThread->GetNoteDriver();
    820   if (!pNoteDriver)
    821     return;
    822   pNoteDriver->RegisterEventTarget(m_pInterface, pEventSource, dwFilter);
    823 }
    824 void CFWL_WidgetImp::UnregisterEventTarget() {
    825   IFWL_NoteThread* pThread = GetOwnerThread();
    826   if (!pThread)
    827     return;
    828   IFWL_NoteDriver* pNoteDriver = pThread->GetNoteDriver();
    829   if (!pNoteDriver)
    830     return;
    831   pNoteDriver->UnregisterEventTarget(m_pInterface);
    832 }
    833 void CFWL_WidgetImp::DispatchKeyEvent(CFWL_MsgKey* pNote) {
    834   if (!pNote)
    835     return;
    836   CFWL_EvtKey* pEvent = new CFWL_EvtKey;
    837   pEvent->m_pSrcTarget = m_pInterface;
    838   pEvent->m_dwCmd = pNote->m_dwCmd;
    839   pEvent->m_dwKeyCode = pNote->m_dwKeyCode;
    840   pEvent->m_dwFlags = pNote->m_dwFlags;
    841   DispatchEvent(pEvent);
    842   pEvent->Release();
    843 }
    844 void CFWL_WidgetImp::DispatchEvent(CFWL_Event* pEvent) {
    845   if (m_pOuter) {
    846     IFWL_WidgetDelegate* pDelegate = m_pOuter->SetDelegate(NULL);
    847     pDelegate->OnProcessEvent(pEvent);
    848     return;
    849   }
    850   IFWL_NoteThread* pThread = GetOwnerThread();
    851   if (!pThread)
    852     return;
    853   IFWL_NoteDriver* pNoteDriver = pThread->GetNoteDriver();
    854   if (!pNoteDriver)
    855     return;
    856   pNoteDriver->SendNote(pEvent);
    857 }
    858 void CFWL_WidgetImp::Repaint(const CFX_RectF* pRect) {
    859   if (pRect) {
    860     m_pWidgetMgr->RepaintWidget(m_pInterface, pRect);
    861     return;
    862   }
    863   CFX_RectF rect;
    864   rect = m_pProperties->m_rtWidget;
    865   rect.left = rect.top = 0;
    866   m_pWidgetMgr->RepaintWidget(m_pInterface, &rect);
    867 }
    868 void CFWL_WidgetImp::DrawBackground(CFX_Graphics* pGraphics,
    869                                     int32_t iPartBk,
    870                                     IFWL_ThemeProvider* pTheme,
    871                                     const CFX_Matrix* pMatrix) {
    872   CFX_RectF rtRelative;
    873   GetRelativeRect(rtRelative);
    874   CFWL_ThemeBackground param;
    875   param.m_pWidget = m_pInterface;
    876   param.m_iPart = iPartBk;
    877   param.m_pGraphics = pGraphics;
    878   if (pMatrix) {
    879     param.m_matrix.Concat(*pMatrix, TRUE);
    880   }
    881   param.m_rtPart = rtRelative;
    882   pTheme->DrawBackground(&param);
    883 }
    884 void CFWL_WidgetImp::DrawBorder(CFX_Graphics* pGraphics,
    885                                 int32_t iPartBorder,
    886                                 IFWL_ThemeProvider* pTheme,
    887                                 const CFX_Matrix* pMatrix) {
    888   CFX_RectF rtRelative;
    889   GetRelativeRect(rtRelative);
    890   CFWL_ThemeBackground param;
    891   param.m_pWidget = m_pInterface;
    892   param.m_iPart = iPartBorder;
    893   param.m_pGraphics = pGraphics;
    894   if (pMatrix) {
    895     param.m_matrix.Concat(*pMatrix, TRUE);
    896   }
    897   param.m_rtPart = rtRelative;
    898   pTheme->DrawBackground(&param);
    899 }
    900 void CFWL_WidgetImp::DrawEdge(CFX_Graphics* pGraphics,
    901                               int32_t iPartEdge,
    902                               IFWL_ThemeProvider* pTheme,
    903                               const CFX_Matrix* pMatrix) {
    904   CFX_RectF rtEdge;
    905   GetEdgeRect(rtEdge);
    906   CFWL_ThemeBackground param;
    907   param.m_pWidget = m_pInterface;
    908   param.m_iPart = iPartEdge;
    909   param.m_pGraphics = pGraphics;
    910   if (pMatrix) {
    911     param.m_matrix.Concat(*pMatrix, TRUE);
    912   }
    913   param.m_rtPart = rtEdge;
    914   pTheme->DrawBackground(&param);
    915 }
    916 void CFWL_WidgetImp::NotifyDriver() {
    917   IFWL_NoteThread* pThread = GetOwnerThread();
    918   if (!pThread)
    919     return;
    920   CFWL_NoteDriver* pDriver =
    921       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    922   if (!pDriver)
    923     return;
    924   pDriver->NotifyTargetDestroy(m_pInterface);
    925 }
    926 CFX_SizeF CFWL_WidgetImp::GetOffsetFromParent(IFWL_Widget* pParent) {
    927   CFX_SizeF szRet;
    928   szRet.Set(0, 0);
    929   if (pParent == GetInterface()) {
    930     return szRet;
    931   }
    932   IFWL_WidgetMgr* pWidgetMgr = FWL_GetWidgetMgr();
    933   if (!pWidgetMgr)
    934     return szRet;
    935   szRet.x += m_pProperties->m_rtWidget.left;
    936   szRet.y += m_pProperties->m_rtWidget.top;
    937   IFWL_Widget* pDstWidget = GetParent();
    938   while (pDstWidget && pDstWidget != pParent) {
    939     CFX_RectF rtDst;
    940     pDstWidget->GetWidgetRect(rtDst);
    941     szRet.x += rtDst.left;
    942     szRet.y += rtDst.top;
    943     pDstWidget = pWidgetMgr->GetWidget(pDstWidget, FWL_WGTRELATION_Parent);
    944   }
    945   return szRet;
    946 }
    947 FX_BOOL CFWL_WidgetImp::IsParent(IFWL_Widget* pParent) {
    948   IFWL_Widget* pUpWidget = GetParent();
    949   while (pUpWidget) {
    950     if (pUpWidget == pParent)
    951       return TRUE;
    952     pUpWidget = pUpWidget->GetParent();
    953   }
    954   return FALSE;
    955 }
    956 CFWL_WidgetImpDelegate::CFWL_WidgetImpDelegate() {}
    957 int32_t CFWL_WidgetImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
    958   if (!pMessage->m_pDstTarget)
    959     return 0;
    960   CFWL_WidgetImp* pWidget =
    961       static_cast<CFWL_WidgetImp*>(pMessage->m_pDstTarget->GetImpl());
    962   FX_DWORD dwMsgCode = pMessage->GetClassID();
    963   switch (dwMsgCode) {
    964     case FWL_MSGHASH_Mouse: {
    965       CFWL_MsgMouse* pMsgMouse = static_cast<CFWL_MsgMouse*>(pMessage);
    966       CFWL_EvtMouse evt;
    967       evt.m_pSrcTarget = pWidget->m_pInterface;
    968       evt.m_pDstTarget = pWidget->m_pInterface;
    969       evt.m_dwCmd = pMsgMouse->m_dwCmd;
    970       evt.m_dwFlags = pMsgMouse->m_dwFlags;
    971       evt.m_fx = pMsgMouse->m_fx;
    972       evt.m_fy = pMsgMouse->m_fy;
    973       pWidget->DispatchEvent(&evt);
    974       break;
    975     }
    976     case FWL_MSGHASH_MouseWheel: {
    977       CFWL_MsgMouseWheel* pMsgMouseWheel =
    978           static_cast<CFWL_MsgMouseWheel*>(pMessage);
    979       CFWL_EvtMouseWheel evt;
    980       evt.m_pSrcTarget = pWidget->m_pInterface;
    981       evt.m_pDstTarget = pWidget->m_pInterface;
    982       evt.m_dwFlags = pMsgMouseWheel->m_dwFlags;
    983       evt.m_fDeltaX = pMsgMouseWheel->m_fDeltaX;
    984       evt.m_fDeltaY = pMsgMouseWheel->m_fDeltaY;
    985       evt.m_fx = pMsgMouseWheel->m_fx;
    986       evt.m_fy = pMsgMouseWheel->m_fy;
    987       pWidget->DispatchEvent(&evt);
    988       break;
    989     }
    990     case FWL_MSGHASH_Key: {
    991       CFWL_MsgKey* pMsgKey = static_cast<CFWL_MsgKey*>(pMessage);
    992       CFWL_EvtKey evt;
    993       evt.m_pSrcTarget = pWidget->m_pInterface;
    994       evt.m_pDstTarget = pWidget->m_pInterface;
    995       evt.m_dwKeyCode = pMsgKey->m_dwKeyCode;
    996       evt.m_dwFlags = pMsgKey->m_dwFlags;
    997       evt.m_dwCmd = pMsgKey->m_dwCmd;
    998       pWidget->DispatchEvent(&evt);
    999       break;
   1000     }
   1001     case FWL_MSGHASH_SetFocus: {
   1002       CFWL_MsgSetFocus* pMsgSetFocus = static_cast<CFWL_MsgSetFocus*>(pMessage);
   1003       CFWL_EvtSetFocus evt;
   1004       evt.m_pSrcTarget = pMsgSetFocus->m_pDstTarget;
   1005       evt.m_pDstTarget = pMsgSetFocus->m_pDstTarget;
   1006       evt.m_pSetFocus = pWidget->m_pInterface;
   1007       pWidget->DispatchEvent(&evt);
   1008       break;
   1009     }
   1010     case FWL_MSGHASH_KillFocus: {
   1011       CFWL_MsgKillFocus* pMsgKillFocus =
   1012           static_cast<CFWL_MsgKillFocus*>(pMessage);
   1013       CFWL_EvtKillFocus evt;
   1014       evt.m_pSrcTarget = pMsgKillFocus->m_pDstTarget;
   1015       evt.m_pDstTarget = pMsgKillFocus->m_pDstTarget;
   1016       evt.m_pKillFocus = pWidget->m_pInterface;
   1017       pWidget->DispatchEvent(&evt);
   1018       break;
   1019     }
   1020     default: {}
   1021   }
   1022   return 1;
   1023 }
   1024 FWL_ERR CFWL_WidgetImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
   1025   return FWL_ERR_Succeeded;
   1026 }
   1027 FWL_ERR CFWL_WidgetImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
   1028                                              const CFX_Matrix* pMatrix) {
   1029   CFWL_EvtDraw evt;
   1030   evt.m_pGraphics = pGraphics;
   1031   return FWL_ERR_Succeeded;
   1032 }
   1033 class CFWL_CustomImp : public CFWL_WidgetImp {
   1034  public:
   1035   CFWL_CustomImp(const CFWL_WidgetImpProperties& properties,
   1036                  IFWL_Widget* pOuter);
   1037   virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE);
   1038   virtual FWL_ERR Update();
   1039   virtual FWL_ERR SetProxy(IFWL_Proxy* pProxy);
   1040 
   1041  protected:
   1042   IFWL_Proxy* m_pProxy;
   1043 };
   1044 CFWL_CustomImp::CFWL_CustomImp(const CFWL_WidgetImpProperties& properties,
   1045                                IFWL_Widget* pOuter)
   1046     : CFWL_WidgetImp(properties, pOuter), m_pProxy(NULL) {}
   1047 FWL_ERR CFWL_CustomImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
   1048   if (m_pProxy &&
   1049       (m_pProxy->GetWidgetRect(rect, bAutoSize) == FWL_ERR_Succeeded)) {
   1050     return FWL_ERR_Succeeded;
   1051   }
   1052   return CFWL_WidgetImp::GetWidgetRect(rect, bAutoSize);
   1053 }
   1054 FWL_ERR CFWL_CustomImp::Update() {
   1055   if (m_pProxy) {
   1056     return m_pProxy->Update();
   1057   }
   1058   return CFWL_WidgetImp::Update();
   1059 }
   1060 FWL_ERR CFWL_CustomImp::SetProxy(IFWL_Proxy* pProxy) {
   1061   m_pProxy = pProxy;
   1062   return FWL_ERR_Succeeded;
   1063 }
   1064 
   1065 // static
   1066 IFWL_Custom* IFWL_Custom::Create(const CFWL_WidgetImpProperties& properties,
   1067                                  IFWL_Widget* pOuter) {
   1068   IFWL_Custom* pCustom = new IFWL_Custom;
   1069   CFWL_CustomImp* pCustomImpl = new CFWL_CustomImp(properties, pOuter);
   1070   pCustom->SetImpl(pCustomImpl);
   1071   pCustomImpl->SetInterface(pCustom);
   1072   return pCustom;
   1073 }
   1074 IFWL_Custom::IFWL_Custom() {}
   1075 FWL_ERR IFWL_Custom::SetProxy(IFWL_Proxy* pProxy) {
   1076   return static_cast<CFWL_CustomImp*>(GetImpl())->SetProxy(pProxy);
   1077 }
   1078 void FWL_SetWidgetRect(IFWL_Widget* widget, const CFX_RectF& rect) {
   1079   static_cast<CFWL_WidgetImp*>(widget->GetImpl())->m_pProperties->m_rtWidget =
   1080       rect;
   1081 }
   1082 void FWL_SetWidgetStates(IFWL_Widget* widget, FX_DWORD dwStates) {
   1083   static_cast<CFWL_WidgetImp*>(widget->GetImpl())->m_pProperties->m_dwStates =
   1084       dwStates;
   1085 }
   1086 void FWL_SetWidgetStyles(IFWL_Widget* widget, FX_DWORD dwStyles) {
   1087   static_cast<CFWL_WidgetImp*>(widget->GetImpl())->m_pProperties->m_dwStyles =
   1088       dwStyles;
   1089 }
   1090 FWL_ERR FWL_EnabelWidget(IFWL_Widget* widget, FX_BOOL bEnable) {
   1091   widget->SetStates(FWL_WGTSTATE_Disabled, !bEnable);
   1092   IFWL_WidgetMgr* widgetMgr = FWL_GetWidgetMgr();
   1093   IFWL_Widget* child = widgetMgr->GetWidget(widget, FWL_WGTRELATION_FirstChild);
   1094   while (child) {
   1095     FWL_EnabelWidget(child, bEnable);
   1096     child = widgetMgr->GetWidget(child, FWL_WGTRELATION_NextSibling);
   1097   }
   1098   return FWL_ERR_Succeeded;
   1099 }
   1100