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 "xfa/src/foxitlib.h"
      8 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
      9 #include "xfa/src/fwl/src/core/include/fwl_threadimp.h"
     10 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
     11 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
     12 #include "xfa/src/fwl/src/core/include/fwl_contentimp.h"
     13 #include "xfa/src/fwl/src/core/include/fwl_gridimp.h"
     14 
     15 // static
     16 IFWL_Grid* IFWL_Grid::Create(const CFWL_WidgetImpProperties& properties) {
     17   IFWL_Grid* pGrid = new IFWL_Grid;
     18   CFWL_GridImp* pGridImpl = new CFWL_GridImp(properties, nullptr);
     19   pGrid->SetImpl(pGridImpl);
     20   pGridImpl->SetInterface(pGrid);
     21   return pGrid;
     22 }
     23 IFWL_Grid::IFWL_Grid() {}
     24 FWL_HGRIDCOLROW IFWL_Grid::InsertColRow(FX_BOOL bColumn, int32_t nIndex) {
     25   return static_cast<CFWL_GridImp*>(GetImpl())->InsertColRow(bColumn, nIndex);
     26 }
     27 int32_t IFWL_Grid::CountColRows(FX_BOOL bColumn) {
     28   return static_cast<CFWL_GridImp*>(GetImpl())->CountColRows(bColumn);
     29 }
     30 FWL_HGRIDCOLROW IFWL_Grid::GetColRow(FX_BOOL bColumn, int32_t nIndex) {
     31   return static_cast<CFWL_GridImp*>(GetImpl())->GetColRow(bColumn, nIndex);
     32 }
     33 int32_t IFWL_Grid::GetIndex(FWL_HGRIDCOLROW hColRow) {
     34   return static_cast<CFWL_GridImp*>(GetImpl())->GetIndex(hColRow);
     35 }
     36 FX_FLOAT IFWL_Grid::GetSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit) {
     37   return static_cast<CFWL_GridImp*>(GetImpl())->GetSize(hColRow, eUnit);
     38 }
     39 FWL_ERR IFWL_Grid::SetSize(FWL_HGRIDCOLROW hColRow,
     40                            FX_FLOAT fSize,
     41                            FWL_GRIDUNIT eUnit) {
     42   return static_cast<CFWL_GridImp*>(GetImpl())->SetSize(hColRow, fSize, eUnit);
     43 }
     44 FX_FLOAT IFWL_Grid::GetMinSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit) {
     45   return static_cast<CFWL_GridImp*>(GetImpl())->GetMinSize(hColRow, eUnit);
     46 }
     47 FWL_ERR IFWL_Grid::SetMinSize(FWL_HGRIDCOLROW hColRow,
     48                               FX_FLOAT fSize,
     49                               FWL_GRIDUNIT eUnit) {
     50   return static_cast<CFWL_GridImp*>(GetImpl())
     51       ->SetMinSize(hColRow, fSize, eUnit);
     52 }
     53 FX_FLOAT IFWL_Grid::GetMaxSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit) {
     54   return static_cast<CFWL_GridImp*>(GetImpl())->GetMaxSize(hColRow, eUnit);
     55 }
     56 FWL_ERR IFWL_Grid::SetMaxSize(FWL_HGRIDCOLROW hColRow,
     57                               FX_FLOAT fSize,
     58                               FWL_GRIDUNIT eUnit) {
     59   return static_cast<CFWL_GridImp*>(GetImpl())
     60       ->SetMaxSize(hColRow, fSize, eUnit);
     61 }
     62 FX_BOOL IFWL_Grid::DeleteColRow(FWL_HGRIDCOLROW hColRow) {
     63   return static_cast<CFWL_GridImp*>(GetImpl())->DeleteColRow(hColRow);
     64 }
     65 FX_BOOL IFWL_Grid::IsColumn(FWL_HGRIDCOLROW hColRow) {
     66   return static_cast<CFWL_GridImp*>(GetImpl())->IsColumn(hColRow);
     67 }
     68 int32_t IFWL_Grid::GetWidgetPos(IFWL_Widget* pWidget, FX_BOOL bColumn) {
     69   return static_cast<CFWL_GridImp*>(GetImpl())->GetWidgetPos(pWidget, bColumn);
     70 }
     71 FWL_ERR IFWL_Grid::SetWidgetPos(IFWL_Widget* pWidget,
     72                                 int32_t iPos,
     73                                 FX_BOOL bColumn) {
     74   return static_cast<CFWL_GridImp*>(GetImpl())
     75       ->SetWidgetPos(pWidget, iPos, bColumn);
     76 }
     77 int32_t IFWL_Grid::GetWidgetSpan(IFWL_Widget* pWidget, FX_BOOL bColumn) {
     78   return static_cast<CFWL_GridImp*>(GetImpl())->GetWidgetSpan(pWidget, bColumn);
     79 }
     80 FWL_ERR IFWL_Grid::SetWidgetSpan(IFWL_Widget* pWidget,
     81                                  int32_t iSpan,
     82                                  FX_BOOL bColumn) {
     83   return static_cast<CFWL_GridImp*>(GetImpl())
     84       ->SetWidgetSpan(pWidget, iSpan, bColumn);
     85 }
     86 FX_FLOAT IFWL_Grid::GetWidgetSize(IFWL_Widget* pWidget,
     87                                   FWL_GRIDSIZE eSize,
     88                                   FWL_GRIDUNIT& eUnit) {
     89   return static_cast<CFWL_GridImp*>(GetImpl())
     90       ->GetWidgetSize(pWidget, eSize, eUnit);
     91 }
     92 FWL_ERR IFWL_Grid::SetWidgetSize(IFWL_Widget* pWidget,
     93                                  FWL_GRIDSIZE eSize,
     94                                  FX_FLOAT fSize,
     95                                  FWL_GRIDUNIT eUit) {
     96   return static_cast<CFWL_GridImp*>(GetImpl())
     97       ->SetWidgetSize(pWidget, eSize, fSize, eUit);
     98 }
     99 FX_BOOL IFWL_Grid::GetWidgetMargin(IFWL_Widget* pWidget,
    100                                    FWL_GRIDMARGIN eMargin,
    101                                    FX_FLOAT& fMargin) {
    102   return static_cast<CFWL_GridImp*>(GetImpl())
    103       ->GetWidgetMargin(pWidget, eMargin, fMargin);
    104 }
    105 FWL_ERR IFWL_Grid::SetWidgetMargin(IFWL_Widget* pWidget,
    106                                    FWL_GRIDMARGIN eMargin,
    107                                    FX_FLOAT fMargin) {
    108   return static_cast<CFWL_GridImp*>(GetImpl())
    109       ->SetWidgetMargin(pWidget, eMargin, fMargin);
    110 }
    111 FWL_ERR IFWL_Grid::RemoveWidgetMargin(IFWL_Widget* pWidget,
    112                                       FWL_GRIDMARGIN eMargin) {
    113   return static_cast<CFWL_GridImp*>(GetImpl())
    114       ->RemoveWidgetMargin(pWidget, eMargin);
    115 }
    116 FX_FLOAT IFWL_Grid::GetGridSize(FWL_GRIDSIZE eSize, FWL_GRIDUNIT& eUnit) {
    117   return static_cast<CFWL_GridImp*>(GetImpl())->GetGridSize(eSize, eUnit);
    118 }
    119 FWL_ERR IFWL_Grid::SetGridSize(FWL_GRIDSIZE eSize,
    120                                FX_FLOAT fSize,
    121                                FWL_GRIDUNIT eUit) {
    122   return static_cast<CFWL_GridImp*>(GetImpl())->SetGridSize(eSize, fSize, eUit);
    123 }
    124 
    125 CFWL_GridImp::CFWL_GridImp(const CFWL_WidgetImpProperties& properties,
    126                            IFWL_Widget* pOuter)
    127     : CFWL_ContentImp(properties, pOuter) {
    128   m_Size[FWL_GRIDSIZE_Width].eUnit = FWL_GRIDUNIT_Auto;
    129   m_Size[FWL_GRIDSIZE_Width].fLength = 0;
    130   m_Size[FWL_GRIDSIZE_Height].eUnit = FWL_GRIDUNIT_Auto;
    131   m_Size[FWL_GRIDSIZE_Height].fLength = 0;
    132   m_Size[FWL_GRIDSIZE_MinWidth].eUnit = FWL_GRIDUNIT_Fixed;
    133   m_Size[FWL_GRIDSIZE_MinWidth].fLength = 0;
    134   m_Size[FWL_GRIDSIZE_MaxWidth].eUnit = FWL_GRIDUNIT_Infinity;
    135   m_Size[FWL_GRIDSIZE_MaxWidth].fLength = 0;
    136   m_Size[FWL_GRIDSIZE_MinHeight].eUnit = FWL_GRIDUNIT_Fixed;
    137   m_Size[FWL_GRIDSIZE_MinHeight].fLength = 0;
    138   m_Size[FWL_GRIDSIZE_MaxHeight].eUnit = FWL_GRIDUNIT_Infinity;
    139   m_Size[FWL_GRIDSIZE_MaxHeight].fLength = 0;
    140 }
    141 CFWL_GridImp::~CFWL_GridImp() {
    142   int32_t iCount = m_Columns.GetSize();
    143   for (int32_t i = 0; i < iCount; i++) {
    144     delete static_cast<CFWL_GridColRow*>(m_Columns[i]);
    145   }
    146   m_Columns.RemoveAll();
    147   iCount = m_Rows.GetSize();
    148   for (int32_t j = 0; j < iCount; j++) {
    149     delete static_cast<CFWL_GridColRow*>(m_Rows[j]);
    150   }
    151   m_Rows.RemoveAll();
    152   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
    153   while (ps) {
    154     IFWL_Widget* pWidget;
    155     CFWL_GridWidgetInfo* pInfo;
    156     m_mapWidgetInfo.GetNextAssoc(ps, (void*&)pWidget, (void*&)pInfo);
    157     delete pInfo;
    158   }
    159   m_mapWidgetInfo.RemoveAll();
    160   delete m_pDelegate;
    161   m_pDelegate = nullptr;
    162 }
    163 FWL_ERR CFWL_GridImp::GetClassName(CFX_WideString& wsClass) const {
    164   wsClass = FWL_CLASS_Grid;
    165   return FWL_ERR_Succeeded;
    166 }
    167 FX_DWORD CFWL_GridImp::GetClassID() const {
    168   return FWL_CLASSHASH_Grid;
    169 }
    170 FWL_ERR CFWL_GridImp::Initialize() {
    171   if (CFWL_ContentImp::Initialize() != FWL_ERR_Succeeded)
    172     return FWL_ERR_Indefinite;
    173   m_pDelegate = new CFWL_GridImpDelegate(this);
    174   return FWL_ERR_Succeeded;
    175 }
    176 FWL_ERR CFWL_GridImp::Finalize() {
    177   if (CFWL_ContentImp::Finalize() != FWL_ERR_Succeeded)
    178     return FWL_ERR_Indefinite;
    179   delete m_pDelegate;
    180   m_pDelegate = nullptr;
    181   return FWL_ERR_Succeeded;
    182 }
    183 FWL_ERR CFWL_GridImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
    184   if (bAutoSize) {
    185     rect.left = 0;
    186     rect.top = 0;
    187     rect.width = ProcessUnCertainColumns();
    188     rect.height = ProcessUnCertainRows();
    189   } else {
    190     rect = m_pProperties->m_rtWidget;
    191   }
    192   return FWL_ERR_Succeeded;
    193 }
    194 FWL_ERR CFWL_GridImp::SetWidgetRect(const CFX_RectF& rect) {
    195   CFWL_WidgetImp::SetWidgetRect(rect);
    196   return FWL_ERR_Succeeded;
    197 }
    198 FWL_ERR CFWL_GridImp::Update() {
    199   if (IsLocked()) {
    200     return FWL_ERR_Indefinite;
    201   }
    202   ProcessColumns(m_pProperties->m_rtWidget.width);
    203   ProcessRows(m_pProperties->m_rtWidget.height);
    204   SetAllWidgetsRect();
    205   return FWL_ERR_Succeeded;
    206 }
    207 FWL_ERR CFWL_GridImp::DrawWidget(CFX_Graphics* pGraphics,
    208                                  const CFX_Matrix* pMatrix) {
    209   if (!pGraphics)
    210     return FWL_ERR_Indefinite;
    211   if ((m_pProperties->m_dwStyleExes & FWL_GRIDSTYLEEXT_ShowGridLines) == 0) {
    212     return FWL_ERR_Succeeded;
    213   }
    214   pGraphics->SaveGraphState();
    215   if (pMatrix) {
    216     pGraphics->ConcatMatrix(pMatrix);
    217   }
    218   {
    219     FX_BOOL bDrawLine = FALSE;
    220     CFX_Path path;
    221     path.Create();
    222     int32_t iColumns = m_Columns.GetSize();
    223     for (int32_t i = 1; i < iColumns; i++) {
    224       CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(m_Columns[i]);
    225       if (!pColRow) {
    226         continue;
    227       }
    228       bDrawLine = TRUE;
    229       path.AddLine(pColRow->m_fActualPos, 0, pColRow->m_fActualPos,
    230                    m_pProperties->m_rtWidget.height);
    231     }
    232     int32_t iRows = m_Rows.GetSize();
    233     for (int32_t j = 1; j < iRows; j++) {
    234       CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(m_Rows[j]);
    235       if (!pColRow) {
    236         continue;
    237       }
    238       bDrawLine = TRUE;
    239       path.AddLine(0, pColRow->m_fActualPos, m_pProperties->m_rtWidget.width,
    240                    pColRow->m_fActualPos);
    241     }
    242     if (bDrawLine) {
    243       CFX_Color cr(0xFFFF0000);
    244       pGraphics->SetStrokeColor(&cr);
    245       pGraphics->StrokePath(&path);
    246     }
    247   }
    248   pGraphics->RestoreGraphState();
    249   return FWL_ERR_Succeeded;
    250 }
    251 FWL_ERR CFWL_GridImp::InsertWidget(IFWL_Widget* pChild, int32_t nIndex) {
    252   if (!pChild)
    253     return FWL_ERR_Indefinite;
    254   CFWL_ContentImp::InsertWidget(pChild, nIndex);
    255   if (!m_mapWidgetInfo.GetValueAt(pChild)) {
    256     CFWL_GridWidgetInfo* pInfo = new CFWL_GridWidgetInfo;
    257     m_mapWidgetInfo.SetAt(pChild, pInfo);
    258     m_Widgets.Add(pChild);
    259   }
    260   return FWL_ERR_Succeeded;
    261 }
    262 FWL_ERR CFWL_GridImp::RemoveWidget(IFWL_Widget* pWidget) {
    263   if (!pWidget)
    264     return FWL_ERR_Indefinite;
    265   CFWL_ContentImp::RemoveWidget(pWidget);
    266   if (CFWL_GridWidgetInfo* pInfo = static_cast<CFWL_GridWidgetInfo*>(
    267           m_mapWidgetInfo.GetValueAt(pWidget))) {
    268     m_mapWidgetInfo.RemoveKey(pWidget);
    269     delete pInfo;
    270     int32_t nIndex = m_Widgets.Find(pWidget);
    271     m_Widgets.RemoveAt(nIndex, 1);
    272   }
    273   return FWL_ERR_Succeeded;
    274 }
    275 FWL_HGRIDCOLROW CFWL_GridImp::InsertColRow(FX_BOOL bColumn, int32_t nIndex) {
    276   if (bColumn) {
    277     if (nIndex < 0 || nIndex > m_Columns.GetSize()) {
    278       nIndex = m_Columns.GetSize();
    279     }
    280     CFWL_GridColRow* pColumn = new CFWL_GridColRow;
    281     m_Columns.InsertAt(nIndex, pColumn, 1);
    282     return (FWL_HGRIDCOLROW)pColumn;
    283   }
    284   if (nIndex < 0 || nIndex > m_Rows.GetSize()) {
    285     nIndex = m_Rows.GetSize();
    286   }
    287   CFWL_GridColRow* pRow = new CFWL_GridColRow;
    288   m_Rows.InsertAt(nIndex, pRow, 1);
    289   return (FWL_HGRIDCOLROW)pRow;
    290 }
    291 int32_t CFWL_GridImp::CountColRows(FX_BOOL bColumn) {
    292   if (bColumn) {
    293     return m_Columns.GetSize();
    294   }
    295   return m_Rows.GetSize();
    296 }
    297 FWL_HGRIDCOLROW CFWL_GridImp::GetColRow(FX_BOOL bColumn, int32_t nIndex) {
    298   if (bColumn) {
    299     if (nIndex < 0 || nIndex >= m_Columns.GetSize()) {
    300       return NULL;
    301     }
    302     return (FWL_HGRIDCOLROW)m_Columns[nIndex];
    303   }
    304   if (nIndex < 0 || nIndex >= m_Rows.GetSize()) {
    305     return NULL;
    306   }
    307   return (FWL_HGRIDCOLROW)m_Rows[nIndex];
    308 }
    309 int32_t CFWL_GridImp::GetIndex(FWL_HGRIDCOLROW hColRow) {
    310   if (IsColumn(hColRow)) {
    311     return m_Columns.Find(hColRow);
    312   }
    313   return m_Rows.Find(hColRow);
    314 }
    315 FX_FLOAT CFWL_GridImp::GetSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit) {
    316   if (!hColRow)
    317     return -1;
    318   CFWL_GridColRow* pColRow = reinterpret_cast<CFWL_GridColRow*>(hColRow);
    319   eUnit = pColRow->m_Size.eUnit;
    320   return pColRow->m_Size.fLength;
    321 }
    322 FWL_ERR CFWL_GridImp::SetSize(FWL_HGRIDCOLROW hColRow,
    323                               FX_FLOAT fSize,
    324                               FWL_GRIDUNIT eUnit) {
    325   if (!hColRow)
    326     return FWL_ERR_Indefinite;
    327   CFWL_GridColRow* pColRow = reinterpret_cast<CFWL_GridColRow*>(hColRow);
    328   pColRow->m_Size.eUnit = eUnit;
    329   pColRow->m_Size.fLength = fSize;
    330   return FWL_ERR_Succeeded;
    331 }
    332 FX_FLOAT CFWL_GridImp::GetMinSize(FWL_HGRIDCOLROW hColRow,
    333                                   FWL_GRIDUNIT& eUnit) {
    334   if (!hColRow)
    335     return -1;
    336   CFWL_GridColRow* pColRow = reinterpret_cast<CFWL_GridColRow*>(hColRow);
    337   eUnit = pColRow->m_MinSize.eUnit;
    338   return pColRow->m_MinSize.fLength;
    339 }
    340 FWL_ERR CFWL_GridImp::SetMinSize(FWL_HGRIDCOLROW hColRow,
    341                                  FX_FLOAT fSize,
    342                                  FWL_GRIDUNIT eUnit) {
    343   if (!hColRow)
    344     return FWL_ERR_Indefinite;
    345   CFWL_GridColRow* pColRow = reinterpret_cast<CFWL_GridColRow*>(hColRow);
    346   pColRow->m_MinSize.eUnit = eUnit;
    347   pColRow->m_MinSize.fLength = fSize;
    348   return FWL_ERR_Succeeded;
    349 }
    350 FX_FLOAT CFWL_GridImp::GetMaxSize(FWL_HGRIDCOLROW hColRow,
    351                                   FWL_GRIDUNIT& eUnit) {
    352   if (!hColRow)
    353     return -1;
    354   CFWL_GridColRow* pColRow = reinterpret_cast<CFWL_GridColRow*>(hColRow);
    355   eUnit = pColRow->m_MaxSize.eUnit;
    356   return pColRow->m_MaxSize.fLength;
    357 }
    358 FWL_ERR CFWL_GridImp::SetMaxSize(FWL_HGRIDCOLROW hColRow,
    359                                  FX_FLOAT fSize,
    360                                  FWL_GRIDUNIT eUnit) {
    361   if (!hColRow)
    362     return FWL_ERR_Indefinite;
    363   CFWL_GridColRow* pColRow = reinterpret_cast<CFWL_GridColRow*>(hColRow);
    364   pColRow->m_MaxSize.eUnit = eUnit;
    365   pColRow->m_MaxSize.fLength = fSize;
    366   return FWL_ERR_Succeeded;
    367 }
    368 FX_BOOL CFWL_GridImp::DeleteColRow(FWL_HGRIDCOLROW hColRow) {
    369   int32_t nIndex = m_Columns.Find(hColRow);
    370   if (nIndex >= 0) {
    371     m_Columns.RemoveAt(nIndex);
    372     delete reinterpret_cast<CFWL_GridColRow*>(hColRow);
    373     return TRUE;
    374   }
    375   nIndex = m_Rows.Find(hColRow);
    376   if (nIndex >= 0) {
    377     delete reinterpret_cast<CFWL_GridColRow*>(hColRow);
    378     m_Rows.RemoveAt(nIndex);
    379     return TRUE;
    380   }
    381   return FALSE;
    382 }
    383 FX_BOOL CFWL_GridImp::IsColumn(FWL_HGRIDCOLROW hColRow) {
    384   return m_Columns.Find(hColRow) != -1;
    385 }
    386 int32_t CFWL_GridImp::GetWidgetPos(IFWL_Widget* pWidget, FX_BOOL bColumn) {
    387   CFWL_GridWidgetInfo* pInfo =
    388       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    389   if (pInfo) {
    390     return bColumn ? pInfo->m_iColumn : pInfo->m_iRow;
    391   }
    392   return -1;
    393 }
    394 FWL_ERR CFWL_GridImp::SetWidgetPos(IFWL_Widget* pWidget,
    395                                    int32_t iPos,
    396                                    FX_BOOL bColumn) {
    397   CFWL_GridWidgetInfo* pInfo =
    398       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    399   if (pInfo) {
    400     bColumn ? pInfo->m_iColumn = iPos : pInfo->m_iRow = iPos;
    401   }
    402   return FWL_ERR_Succeeded;
    403 }
    404 int32_t CFWL_GridImp::GetWidgetSpan(IFWL_Widget* pWidget, FX_BOOL bColumn) {
    405   CFWL_GridWidgetInfo* pInfo =
    406       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    407   if (pInfo) {
    408     return bColumn ? pInfo->m_iColumnSpan : pInfo->m_iRowSpan;
    409   }
    410   return 0;
    411 }
    412 FWL_ERR CFWL_GridImp::SetWidgetSpan(IFWL_Widget* pWidget,
    413                                     int32_t iSpan,
    414                                     FX_BOOL bColumn) {
    415   CFWL_GridWidgetInfo* pInfo =
    416       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    417   if (pInfo) {
    418     bColumn ? pInfo->m_iColumnSpan = iSpan : pInfo->m_iRowSpan = iSpan;
    419   }
    420   return FWL_ERR_Succeeded;
    421 }
    422 FX_FLOAT CFWL_GridImp::GetWidgetSize(IFWL_Widget* pWidget,
    423                                      FWL_GRIDSIZE eSize,
    424                                      FWL_GRIDUNIT& eUnit) {
    425   CFWL_GridWidgetInfo* pInfo =
    426       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    427   if (pInfo) {
    428     eUnit = pInfo->m_Size[eSize].eUnit;
    429     return pInfo->m_Size[eSize].fLength;
    430   }
    431   return 0;
    432 }
    433 FWL_ERR CFWL_GridImp::SetWidgetSize(IFWL_Widget* pWidget,
    434                                     FWL_GRIDSIZE eSize,
    435                                     FX_FLOAT fSize,
    436                                     FWL_GRIDUNIT eUit) {
    437   CFWL_GridWidgetInfo* pInfo =
    438       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    439   if (pInfo) {
    440     pInfo->m_Size[eSize].fLength = fSize;
    441     pInfo->m_Size[eSize].eUnit = eUit;
    442   }
    443   return FWL_ERR_Succeeded;
    444 }
    445 FX_BOOL CFWL_GridImp::GetWidgetMargin(IFWL_Widget* pWidget,
    446                                       FWL_GRIDMARGIN eMargin,
    447                                       FX_FLOAT& fMargin) {
    448   CFWL_GridWidgetInfo* pInfo =
    449       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    450   if (pInfo) {
    451     fMargin = pInfo->m_Margin[eMargin];
    452     return (pInfo->m_dwMarginFlag & (1 << eMargin)) != 0;
    453   }
    454   return FALSE;
    455 }
    456 FWL_ERR CFWL_GridImp::SetWidgetMargin(IFWL_Widget* pWidget,
    457                                       FWL_GRIDMARGIN eMargin,
    458                                       FX_FLOAT fMargin) {
    459   CFWL_GridWidgetInfo* pInfo =
    460       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    461   if (pInfo) {
    462     pInfo->m_Margin[eMargin] = fMargin;
    463     pInfo->m_dwMarginFlag |= (1 << eMargin);
    464   }
    465   return FWL_ERR_Succeeded;
    466 }
    467 FWL_ERR CFWL_GridImp::RemoveWidgetMargin(IFWL_Widget* pWidget,
    468                                          FWL_GRIDMARGIN eMargin) {
    469   CFWL_GridWidgetInfo* pInfo =
    470       static_cast<CFWL_GridWidgetInfo*>(GetWidgetInfo(pWidget));
    471   if (pInfo) {
    472     pInfo->m_dwMarginFlag &= ~(1 << eMargin);
    473   }
    474   return FWL_ERR_Succeeded;
    475 }
    476 FX_FLOAT CFWL_GridImp::GetGridSize(FWL_GRIDSIZE eSize, FWL_GRIDUNIT& eUnit) {
    477   eUnit = m_Size[eSize].eUnit;
    478   return m_Size[eSize].fLength;
    479 }
    480 FWL_ERR CFWL_GridImp::SetGridSize(FWL_GRIDSIZE eSize,
    481                                   FX_FLOAT fSize,
    482                                   FWL_GRIDUNIT eUit) {
    483   m_Size[eSize].fLength = fSize;
    484   m_Size[eSize].eUnit = eUit;
    485   return FWL_ERR_Succeeded;
    486 }
    487 CFWL_GridWidgetInfo* CFWL_GridImp::GetWidgetInfo(IFWL_Widget* pWidget) {
    488   return static_cast<CFWL_GridWidgetInfo*>(m_mapWidgetInfo.GetValueAt(pWidget));
    489 }
    490 void CFWL_GridImp::ProcFixedColRow(CFWL_GridColRow* pColRow,
    491                                    int32_t nIndex,
    492                                    FX_FLOAT fColRowSize,
    493                                    FX_BOOL bColumn) {
    494   pColRow->m_fActualSize = fColRowSize;
    495   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
    496   while (ps) {
    497     void* key = nullptr;
    498     void* value = nullptr;
    499     m_mapWidgetInfo.GetNextAssoc(ps, key, value);
    500     IFWL_Widget* pWidget = static_cast<IFWL_Widget*>(key);
    501     CFWL_GridWidgetInfo* pInfo = static_cast<CFWL_GridWidgetInfo*>(value);
    502     if (bColumn) {
    503       if (pInfo->m_iColumn == nIndex && pInfo->m_iColumnSpan == 1) {
    504         CalcWidgetWidth(pWidget, pInfo, pColRow->m_fActualSize);
    505       }
    506     } else {
    507       if (pInfo->m_iRow == nIndex && pInfo->m_iRowSpan == 1) {
    508         CalcWidgetHeigt(pWidget, pInfo, pColRow->m_fActualSize);
    509       }
    510     }
    511   }
    512 }
    513 void CFWL_GridImp::ProcAutoColRow(CFWL_GridColRow* pColRow,
    514                                   int32_t nIndex,
    515                                   FX_BOOL bColumn) {
    516   if (!pColRow)
    517     return;
    518   FX_FLOAT fMaxSize = 0, fWidgetSize = 0;
    519   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
    520   while (ps) {
    521     IFWL_Widget* pWidget = NULL;
    522     CFWL_GridWidgetInfo* pInfo = NULL;
    523     m_mapWidgetInfo.GetNextAssoc(ps, (void*&)pWidget, (void*&)pInfo);
    524     if (!pWidget || !pInfo) {
    525       continue;
    526     }
    527     if (bColumn) {
    528       if (pInfo->m_iColumn != nIndex || pInfo->m_iColumnSpan != 1) {
    529         continue;
    530       }
    531       fWidgetSize = CalcAutoColumnWidgetWidth(pWidget, pInfo);
    532       if (fMaxSize < fWidgetSize) {
    533         fMaxSize = fWidgetSize;
    534       }
    535     } else {
    536       if (pInfo->m_iRow != nIndex || pInfo->m_iRowSpan != 1) {
    537         continue;
    538       }
    539       fWidgetSize = CalcAutoColumnWidgetHeight(pWidget, pInfo);
    540       if (fMaxSize < fWidgetSize) {
    541         fMaxSize = fWidgetSize;
    542       }
    543     }
    544   }
    545   SetColRowActualSize(pColRow, fMaxSize);
    546 }
    547 void CFWL_GridImp::ProcScaledColRow(CFWL_GridColRow* pColRow,
    548                                     int32_t nIndex,
    549                                     FX_FLOAT fColRowSize,
    550                                     FX_BOOL bColumn) {
    551   if (fColRowSize > 0) {
    552     ProcFixedColRow(pColRow, nIndex, fColRowSize, bColumn);
    553   }
    554 }
    555 void CFWL_GridImp::CalcWidgetWidth(IFWL_Widget* pWidget,
    556                                    CFWL_GridWidgetInfo* pInfo,
    557                                    FX_FLOAT fColunmWidth) {
    558   if (pInfo->m_Size[FWL_GRIDSIZE_Width].eUnit == FWL_GRIDUNIT_Fixed) {
    559     SetWidgetActualWidth(pInfo, pInfo->m_Size[FWL_GRIDSIZE_Width].fLength);
    560   } else {
    561     FX_FLOAT fWidth = 0;
    562     FX_FLOAT fLeftMargin = 0, fRightMargin = 0;
    563     FX_BOOL bLeftMargin =
    564         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Left, fLeftMargin);
    565     FX_BOOL bRightMargin =
    566         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Right, fRightMargin);
    567     if (bLeftMargin && bRightMargin) {
    568       fWidth = fColunmWidth - fLeftMargin - fRightMargin;
    569     } else {
    570       CFX_RectF rtAuto;
    571       pWidget->GetWidgetRect(rtAuto, TRUE);
    572       fWidth = rtAuto.Width();
    573     }
    574     SetWidgetActualWidth(pInfo, fWidth);
    575   }
    576 }
    577 void CFWL_GridImp::CalcWidgetHeigt(IFWL_Widget* pWidget,
    578                                    CFWL_GridWidgetInfo* pInfo,
    579                                    FX_FLOAT fRowHeigt) {
    580   if (pInfo->m_Size[FWL_GRIDSIZE_Height].eUnit == FWL_GRIDUNIT_Fixed) {
    581     SetWidgetActualHeight(pInfo, pInfo->m_Size[FWL_GRIDSIZE_Height].fLength);
    582   } else {
    583     FX_FLOAT fHeight = 0;
    584     FX_FLOAT fTopMargin = 0, fBottomMargin = 0;
    585     FX_BOOL bTopMargin =
    586         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Top, fTopMargin);
    587     FX_BOOL bBottomMargin =
    588         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Bottom, fBottomMargin);
    589     if (bTopMargin && bBottomMargin) {
    590       fHeight = fRowHeigt - fTopMargin - fBottomMargin;
    591     } else {
    592       CFX_RectF rtAuto;
    593       pWidget->GetWidgetRect(rtAuto, TRUE);
    594       fHeight = rtAuto.Height();
    595     }
    596     SetWidgetActualHeight(pInfo, fHeight);
    597   }
    598 }
    599 FX_FLOAT CFWL_GridImp::CalcAutoColumnWidgetWidth(IFWL_Widget* pWidget,
    600                                                  CFWL_GridWidgetInfo* pInfo) {
    601   FX_FLOAT fLeftMargin = 0, fRightMargin = 0;
    602   FX_BOOL bLeftMargin =
    603       GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Left, fLeftMargin);
    604   FX_BOOL bRightMargin =
    605       GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Right, fRightMargin);
    606   if (pInfo->m_Size[FWL_GRIDSIZE_Width].eUnit == FWL_GRIDUNIT_Fixed) {
    607     SetWidgetActualWidth(pInfo, pInfo->m_Size[FWL_GRIDSIZE_Width].fLength);
    608   } else {
    609     CFX_RectF rtAuto;
    610     pWidget->GetWidgetRect(rtAuto, TRUE);
    611     FX_FLOAT fWidth = rtAuto.width;
    612     SetWidgetActualWidth(pInfo, fWidth);
    613   }
    614   FX_FLOAT fTotal = pInfo->m_fActualWidth;
    615   if (bLeftMargin) {
    616     fTotal += fLeftMargin;
    617   }
    618   if (bRightMargin) {
    619     fTotal += fRightMargin;
    620   }
    621   return fTotal;
    622 }
    623 FX_FLOAT CFWL_GridImp::CalcAutoColumnWidgetHeight(IFWL_Widget* pWidget,
    624                                                   CFWL_GridWidgetInfo* pInfo) {
    625   FX_FLOAT fTopMargin = 0, fBottomMargin = 0;
    626   FX_BOOL bTopMargin = GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Top, fTopMargin);
    627   FX_BOOL bBottomMargin =
    628       GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Bottom, fBottomMargin);
    629   if (pInfo->m_Size[FWL_GRIDSIZE_Height].eUnit == FWL_GRIDUNIT_Fixed) {
    630     SetWidgetActualHeight(pInfo, pInfo->m_Size[FWL_GRIDSIZE_Height].fLength);
    631   } else {
    632     CFX_RectF rtAuto;
    633     pWidget->GetWidgetRect(rtAuto, TRUE);
    634     FX_FLOAT fHeight = rtAuto.height;
    635     SetWidgetActualHeight(pInfo, fHeight);
    636   }
    637   FX_FLOAT fTotal = pInfo->m_fActualHeight;
    638   if (bTopMargin) {
    639     fTotal += fTopMargin;
    640   }
    641   if (bBottomMargin) {
    642     fTotal += fBottomMargin;
    643   }
    644   return fTotal;
    645 }
    646 FX_FLOAT CFWL_GridImp::ProcessColumns(FX_FLOAT fWidth) {
    647   if (fWidth <= 0) {
    648     return ProcessUnCertainColumns();
    649   }
    650   int32_t iColumns = m_Columns.GetSize();
    651   if (iColumns < 1) {
    652     return fWidth;
    653   }
    654   FX_FLOAT fFixedWidth = 0;
    655   FX_FLOAT fAutoWidth = 0;
    656   CFX_PtrArray autoColumns;
    657   CFX_PtrArray scaledColumns;
    658   FX_FLOAT fScaledColumnNum = 0;
    659   for (int32_t i = 0; i < iColumns; i++) {
    660     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(m_Columns[i]);
    661     if (!pColRow) {
    662       continue;
    663     }
    664     switch (pColRow->m_Size.eUnit) {
    665       case FWL_GRIDUNIT_Fixed: {
    666         SetColRowActualSize(pColRow, pColRow->m_Size.fLength);
    667         fFixedWidth += pColRow->m_fActualSize;
    668         break;
    669       }
    670       case FWL_GRIDUNIT_Auto: {
    671         ProcAutoColRow(pColRow, i, TRUE);
    672         autoColumns.Add(pColRow);
    673         break;
    674       }
    675       case FWL_GRIDUNIT_Scaled:
    676       default: {
    677         fScaledColumnNum += pColRow->m_Size.fLength;
    678         scaledColumns.Add(pColRow);
    679         SetColRowActualSize(pColRow, 0);
    680       }
    681     }
    682   }
    683   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
    684   while (ps) {
    685     IFWL_Widget* pWidget = NULL;
    686     CFWL_GridWidgetInfo* pInfo = NULL;
    687     m_mapWidgetInfo.GetNextAssoc(ps, (void*&)pWidget, (void*&)pInfo);
    688     if (!pInfo || pInfo->m_iColumnSpan < 2) {
    689       continue;
    690     }
    691     CFX_PtrArray spanAutoColumns;
    692     FX_FLOAT fSpanSize = 0;
    693     int32_t iAutoColRows = 0;
    694     int32_t iScaledColRows = 0;
    695     for (int32_t i = 0; i < pInfo->m_iColumnSpan; i++) {
    696       CFWL_GridColRow* pColumn = reinterpret_cast<CFWL_GridColRow*>(
    697           GetColRow(TRUE, pInfo->m_iColumn + i));
    698       if (!pColumn) {
    699         break;
    700       }
    701       fSpanSize += pColumn->m_fActualSize;
    702       if (pColumn->m_Size.eUnit == FWL_GRIDUNIT_Auto) {
    703         iAutoColRows++;
    704         spanAutoColumns.Add(pColumn);
    705       } else if (pColumn->m_Size.eUnit == FWL_GRIDUNIT_Scaled) {
    706         iScaledColRows++;
    707       }
    708     }
    709     if (iAutoColRows < 1) {
    710       continue;
    711     }
    712     FX_FLOAT fWidgetWidth = CalcAutoColumnWidgetWidth(pWidget, pInfo);
    713     if (fWidgetWidth > fSpanSize) {
    714       if (iScaledColRows > 0) {
    715       } else {
    716         SetSpanAutoColRowSize(spanAutoColumns, fWidgetWidth - fSpanSize);
    717       }
    718     }
    719   }
    720   int32_t iAutoCols = autoColumns.GetSize();
    721   for (int32_t k = 0; k < iAutoCols; k++) {
    722     fAutoWidth += static_cast<CFWL_GridColRow*>(autoColumns[k])->m_fActualSize;
    723   }
    724   FX_FLOAT fScaledWidth = fWidth - fFixedWidth - fAutoWidth;
    725   if (fScaledWidth > 0 && fScaledColumnNum > 0) {
    726     SetScaledColRowsSize(scaledColumns, fScaledWidth, fScaledColumnNum);
    727   }
    728   return fWidth;
    729 }
    730 FX_FLOAT CFWL_GridImp::ProcessRows(FX_FLOAT fHeight) {
    731   if (fHeight <= 0) {
    732     return ProcessUnCertainRows();
    733   }
    734   int32_t iRows = m_Rows.GetSize();
    735   if (iRows < 1) {
    736     return fHeight;
    737   }
    738   FX_FLOAT fFixedHeight = 0;
    739   FX_FLOAT fAutoHeigt = 0;
    740   CFX_PtrArray autoRows;
    741   CFX_PtrArray scaledRows;
    742   FX_FLOAT fScaledRowNum = 0;
    743   for (int32_t i = 0; i < iRows; i++) {
    744     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(m_Rows[i]);
    745     if (!pColRow) {
    746       continue;
    747     }
    748     switch (pColRow->m_Size.eUnit) {
    749       case FWL_GRIDUNIT_Fixed: {
    750         SetColRowActualSize(pColRow, pColRow->m_Size.fLength);
    751         fFixedHeight += pColRow->m_fActualSize;
    752         break;
    753       }
    754       case FWL_GRIDUNIT_Auto: {
    755         ProcAutoColRow(pColRow, i, FALSE);
    756         autoRows.Add(pColRow);
    757         break;
    758       }
    759       case FWL_GRIDUNIT_Scaled:
    760       default: {
    761         fScaledRowNum += pColRow->m_Size.fLength;
    762         scaledRows.Add(pColRow);
    763         SetColRowActualSize(pColRow, 0);
    764         break;
    765       }
    766     }
    767   }
    768   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
    769   while (ps) {
    770     IFWL_Widget* pWidget = NULL;
    771     CFWL_GridWidgetInfo* pInfo = NULL;
    772     m_mapWidgetInfo.GetNextAssoc(ps, (void*&)pWidget, (void*&)pInfo);
    773     if (!pInfo || pInfo->m_iRowSpan < 2) {
    774       continue;
    775     }
    776     CFX_PtrArray spanAutoRows;
    777     FX_FLOAT fSpanSize = 0;
    778     int32_t iAutoColRows = 0;
    779     int32_t iScaledColRows = 0;
    780     for (int32_t i = 0; i < pInfo->m_iRowSpan; i++) {
    781       CFWL_GridColRow* pRow = reinterpret_cast<CFWL_GridColRow*>(
    782           GetColRow(FALSE, pInfo->m_iRow + i));
    783       if (!pRow) {
    784         break;
    785       }
    786       fSpanSize += pRow->m_fActualSize;
    787       if (pRow->m_Size.eUnit == FWL_GRIDUNIT_Auto) {
    788         iAutoColRows++;
    789         spanAutoRows.Add(pRow);
    790       } else if (pRow->m_Size.eUnit == FWL_GRIDUNIT_Scaled) {
    791         iScaledColRows++;
    792       }
    793     }
    794     if (iAutoColRows < 1) {
    795       continue;
    796     }
    797     FX_FLOAT fWidgetHeight = CalcAutoColumnWidgetHeight(pWidget, pInfo);
    798     if (fWidgetHeight > fSpanSize) {
    799       if (iScaledColRows > 0) {
    800       } else {
    801         SetSpanAutoColRowSize(spanAutoRows, fWidgetHeight - fSpanSize);
    802       }
    803     }
    804   }
    805   int32_t iAutoRows = autoRows.GetSize();
    806   for (int32_t k = 0; k < iAutoRows; k++) {
    807     fAutoHeigt +=
    808         reinterpret_cast<CFWL_GridColRow*>(autoRows[k])->m_fActualSize;
    809   }
    810   FX_FLOAT fScaledHeight = fHeight - fFixedHeight - fAutoHeigt;
    811   if (fScaledHeight > 0 && fScaledRowNum > 0) {
    812     SetScaledColRowsSize(scaledRows, fScaledHeight, fScaledRowNum);
    813   }
    814   return fHeight;
    815 }
    816 FX_FLOAT CFWL_GridImp::ProcessUnCertainColumns() {
    817   int32_t iColumns = m_Columns.GetSize();
    818   if (iColumns < 1) {
    819     CFWL_GridColRow* pColRow = new CFWL_GridColRow;
    820     pColRow->m_Size.eUnit = FWL_GRIDUNIT_Auto;
    821     ProcAutoColRow(pColRow, 0, TRUE);
    822     FX_FLOAT fWidth = pColRow->m_fActualSize;
    823     delete pColRow;
    824     return fWidth;
    825   }
    826   FX_FLOAT fFixedWidth = 0;
    827   CFX_PtrArray autoColumns;
    828   CFX_PtrArray scaledColumns;
    829   FX_FLOAT fScaledColumnNum = 0;
    830   FX_FLOAT fScaledMaxPerWidth = 0;
    831   for (int32_t i = 0; i < iColumns; i++) {
    832     CFWL_GridColRow* pColRow = reinterpret_cast<CFWL_GridColRow*>(m_Columns[i]);
    833     if (!pColRow) {
    834       continue;
    835     }
    836     switch (pColRow->m_Size.eUnit) {
    837       case FWL_GRIDUNIT_Fixed: {
    838         SetColRowActualSize(pColRow, pColRow->m_Size.fLength);
    839         fFixedWidth += pColRow->m_fActualSize;
    840         break;
    841       }
    842       case FWL_GRIDUNIT_Auto: {
    843         ProcAutoColRow(pColRow, i, TRUE);
    844         autoColumns.Add(pColRow);
    845         break;
    846       }
    847       case FWL_GRIDUNIT_Scaled:
    848       default: {
    849         ProcAutoColRow(pColRow, i, TRUE);
    850         fScaledColumnNum += pColRow->m_Size.fLength;
    851         scaledColumns.Add(pColRow);
    852         if (pColRow->m_Size.fLength <= 0) {
    853           break;
    854         }
    855         FX_FLOAT fPerWidth = pColRow->m_fActualSize / pColRow->m_Size.fLength;
    856         if (fPerWidth > fScaledMaxPerWidth) {
    857           fScaledMaxPerWidth = fPerWidth;
    858         }
    859       }
    860     }
    861   }
    862   iColumns = scaledColumns.GetSize();
    863   for (int32_t j = 0; j < iColumns; j++) {
    864     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(scaledColumns[j]);
    865     if (!pColRow) {
    866       continue;
    867     }
    868     SetColRowActualSize(pColRow, fScaledMaxPerWidth * pColRow->m_Size.fLength);
    869   }
    870   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
    871   while (ps) {
    872     IFWL_Widget* pWidget = NULL;
    873     CFWL_GridWidgetInfo* pInfo = NULL;
    874     m_mapWidgetInfo.GetNextAssoc(ps, (void*&)pWidget, (void*&)pInfo);
    875     if (!pInfo || pInfo->m_iColumnSpan < 2) {
    876       continue;
    877     }
    878     CFX_PtrArray spanAutoColumns;
    879     CFX_PtrArray spanScaledColumns;
    880     FX_FLOAT fSpanSize = 0;
    881     FX_FLOAT fScaledSum = 0;
    882     int32_t iAutoColRows = 0;
    883     int32_t iScaledColRows = 0;
    884     for (int32_t i = 0; i < pInfo->m_iColumnSpan; i++) {
    885       CFWL_GridColRow* pColumn = reinterpret_cast<CFWL_GridColRow*>(
    886           GetColRow(TRUE, pInfo->m_iColumn + i));
    887       if (!pColumn) {
    888         break;
    889       }
    890       fSpanSize += pColumn->m_fActualSize;
    891       if (pColumn->m_Size.eUnit == FWL_GRIDUNIT_Auto) {
    892         iAutoColRows++;
    893         spanAutoColumns.Add(pColumn);
    894       } else if (pColumn->m_Size.eUnit == FWL_GRIDUNIT_Scaled) {
    895         iScaledColRows++;
    896         fScaledSum += pColumn->m_Size.fLength;
    897         spanScaledColumns.Add(pColumn);
    898       }
    899     }
    900     if (iAutoColRows < 1 && iScaledColRows < 1) {
    901       continue;
    902     }
    903     FX_FLOAT fWidgetWidth = CalcAutoColumnWidgetWidth(pWidget, pInfo);
    904     if (fWidgetWidth > fSpanSize) {
    905       if (iScaledColRows > 0) {
    906         if (fScaledSum <= 0) {
    907           continue;
    908         }
    909         SetSpanScaledColRowSize(spanScaledColumns, fWidgetWidth - fSpanSize,
    910                                 fScaledSum);
    911       } else {
    912         SetSpanAutoColRowSize(spanAutoColumns, fWidgetWidth - fSpanSize);
    913       }
    914     }
    915   }
    916   FX_FLOAT fAutoWidth = 0;
    917   int32_t iAutoCols = autoColumns.GetSize();
    918   for (int32_t m = 0; m < iAutoCols; m++) {
    919     fAutoWidth += static_cast<CFWL_GridColRow*>(autoColumns[m])->m_fActualSize;
    920   }
    921   FX_FLOAT fScaledWidth = 0;
    922   iColumns = scaledColumns.GetSize();
    923   for (int32_t n = 0; n < iColumns; n++) {
    924     fScaledWidth +=
    925         static_cast<CFWL_GridColRow*>(scaledColumns[n])->m_fActualSize;
    926   }
    927   return fFixedWidth + fAutoWidth + fScaledWidth;
    928 }
    929 FX_FLOAT CFWL_GridImp::ProcessUnCertainRows() {
    930   int32_t iRows = m_Rows.GetSize();
    931   if (iRows < 1) {
    932     CFWL_GridColRow* pColRow = new CFWL_GridColRow;
    933     pColRow->m_Size.eUnit = FWL_GRIDUNIT_Auto;
    934     ProcAutoColRow(pColRow, 0, FALSE);
    935     FX_FLOAT fWidth = pColRow->m_fActualSize;
    936     delete pColRow;
    937     return fWidth;
    938   }
    939   FX_FLOAT fFixedHeight = 0;
    940   CFX_PtrArray autoRows;
    941   CFX_PtrArray scaledRows;
    942   FX_FLOAT fScaledRowNum = 0;
    943   FX_FLOAT fScaledMaxPerHeight = 0;
    944   for (int32_t i = 0; i < iRows; i++) {
    945     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(m_Rows[i]);
    946     if (!pColRow) {
    947       continue;
    948     }
    949     switch (pColRow->m_Size.eUnit) {
    950       case FWL_GRIDUNIT_Fixed: {
    951         SetColRowActualSize(pColRow, pColRow->m_Size.fLength);
    952         fFixedHeight += pColRow->m_fActualSize;
    953         break;
    954       }
    955       case FWL_GRIDUNIT_Auto: {
    956         ProcAutoColRow(pColRow, i, FALSE);
    957         autoRows.Add(pColRow);
    958         break;
    959       }
    960       case FWL_GRIDUNIT_Scaled:
    961       default: {
    962         ProcAutoColRow(pColRow, i, FALSE);
    963         fScaledRowNum += pColRow->m_Size.fLength;
    964         scaledRows.Add(pColRow);
    965         if (pColRow->m_Size.fLength > 0) {
    966           FX_FLOAT fPerHeight =
    967               pColRow->m_fActualSize / pColRow->m_Size.fLength;
    968           if (fPerHeight > fScaledMaxPerHeight) {
    969             fScaledMaxPerHeight = fPerHeight;
    970           }
    971         }
    972         break;
    973       }
    974     }
    975   }
    976   iRows = scaledRows.GetSize();
    977   for (int32_t j = 0; j < iRows; j++) {
    978     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(scaledRows[j]);
    979     if (!pColRow) {
    980       continue;
    981     }
    982     SetColRowActualSize(pColRow, fScaledMaxPerHeight * pColRow->m_Size.fLength);
    983   }
    984   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
    985   while (ps) {
    986     void* key = nullptr;
    987     void* value = nullptr;
    988     m_mapWidgetInfo.GetNextAssoc(ps, key, value);
    989     IFWL_Widget* pWidget = static_cast<IFWL_Widget*>(key);
    990     CFWL_GridWidgetInfo* pInfo = static_cast<CFWL_GridWidgetInfo*>(value);
    991     if (pInfo->m_iRowSpan < 2) {
    992       continue;
    993     }
    994     CFX_PtrArray spanAutoRows;
    995     CFX_PtrArray spanScaledRows;
    996     FX_FLOAT fSpanSize = 0;
    997     FX_FLOAT fScaledSum = 0;
    998     int32_t iAutoColRows = 0;
    999     int32_t iScaledColRows = 0;
   1000     for (int32_t i = 0; i < pInfo->m_iRowSpan; i++) {
   1001       CFWL_GridColRow* pRow = reinterpret_cast<CFWL_GridColRow*>(
   1002           GetColRow(FALSE, pInfo->m_iRow + i));
   1003       if (!pRow) {
   1004         break;
   1005       }
   1006       fSpanSize += pRow->m_fActualSize;
   1007       if (pRow->m_Size.eUnit == FWL_GRIDUNIT_Auto) {
   1008         iAutoColRows++;
   1009         spanAutoRows.Add(pRow);
   1010       } else if (pRow->m_Size.eUnit == FWL_GRIDUNIT_Scaled) {
   1011         iScaledColRows++;
   1012         fScaledSum += pRow->m_Size.fLength;
   1013         spanScaledRows.Add(pRow);
   1014       }
   1015     }
   1016     if (iAutoColRows < 1 && iScaledColRows < 1) {
   1017       continue;
   1018     }
   1019     FX_FLOAT fWidgetHeight = CalcAutoColumnWidgetHeight(pWidget, pInfo);
   1020     if (fWidgetHeight > fSpanSize) {
   1021       if (iScaledColRows > 0) {
   1022         if (fScaledSum <= 0) {
   1023           continue;
   1024         }
   1025         SetSpanScaledColRowSize(spanScaledRows, fWidgetHeight - fSpanSize,
   1026                                 fScaledSum);
   1027       } else {
   1028         SetSpanAutoColRowSize(spanAutoRows, fWidgetHeight - fSpanSize);
   1029       }
   1030     }
   1031   }
   1032   FX_FLOAT fAutoHeigt = 0;
   1033   int32_t iAutoRows = autoRows.GetSize();
   1034   for (int32_t m = 0; m < iAutoRows; m++) {
   1035     fAutoHeigt += static_cast<CFWL_GridColRow*>(autoRows[m])->m_fActualSize;
   1036   }
   1037   FX_FLOAT fScaledHeight = 0;
   1038   iRows = scaledRows.GetSize();
   1039   for (int32_t n = 0; n < iRows; n++) {
   1040     fScaledHeight +=
   1041         static_cast<CFWL_GridColRow*>(scaledRows[n])->m_fActualSize;
   1042   }
   1043   return fFixedHeight + fAutoHeigt + fScaledHeight;
   1044 }
   1045 FX_BOOL CFWL_GridImp::SetColRowActualSize(CFWL_GridColRow* pColRow,
   1046                                           FX_FLOAT fSize,
   1047                                           FX_BOOL bSetBeyond) {
   1048   if (pColRow->m_MinSize.eUnit == FWL_GRIDUNIT_Fixed &&
   1049       fSize < pColRow->m_MinSize.fLength) {
   1050     pColRow->m_fActualSize = pColRow->m_MinSize.fLength;
   1051     return FALSE;
   1052   }
   1053   if (pColRow->m_MaxSize.eUnit == FWL_GRIDUNIT_Fixed &&
   1054       fSize > pColRow->m_MaxSize.fLength) {
   1055     pColRow->m_fActualSize = pColRow->m_MaxSize.fLength;
   1056     return FALSE;
   1057   }
   1058   if (bSetBeyond) {
   1059     return TRUE;
   1060   }
   1061   pColRow->m_fActualSize = fSize;
   1062   return TRUE;
   1063 }
   1064 FX_FLOAT CFWL_GridImp::SetWidgetActualWidth(CFWL_GridWidgetInfo* pInfo,
   1065                                             FX_FLOAT fWidth) {
   1066   if (pInfo->m_Size[FWL_GRIDSIZE_MinWidth].eUnit == FWL_GRIDUNIT_Fixed &&
   1067       fWidth < pInfo->m_Size[FWL_GRIDSIZE_MinWidth].fLength) {
   1068     fWidth = pInfo->m_Size[FWL_GRIDSIZE_MinWidth].fLength;
   1069   }
   1070   if (pInfo->m_Size[FWL_GRIDSIZE_MaxWidth].eUnit == FWL_GRIDUNIT_Fixed &&
   1071       fWidth > pInfo->m_Size[FWL_GRIDSIZE_MaxWidth].fLength) {
   1072     fWidth = pInfo->m_Size[FWL_GRIDSIZE_MaxWidth].fLength;
   1073   }
   1074   pInfo->m_fActualWidth = fWidth;
   1075   return fWidth;
   1076 }
   1077 FX_FLOAT CFWL_GridImp::SetWidgetActualHeight(CFWL_GridWidgetInfo* pInfo,
   1078                                              FX_FLOAT fHeight) {
   1079   if (pInfo->m_Size[FWL_GRIDSIZE_MinHeight].eUnit == FWL_GRIDUNIT_Fixed &&
   1080       fHeight < pInfo->m_Size[FWL_GRIDSIZE_MinHeight].fLength) {
   1081     fHeight = pInfo->m_Size[FWL_GRIDSIZE_MinHeight].fLength;
   1082   }
   1083   if (pInfo->m_Size[FWL_GRIDSIZE_MaxHeight].eUnit == FWL_GRIDUNIT_Fixed &&
   1084       fHeight > pInfo->m_Size[FWL_GRIDSIZE_MaxHeight].fLength) {
   1085     fHeight = pInfo->m_Size[FWL_GRIDSIZE_MaxHeight].fLength;
   1086   }
   1087   pInfo->m_fActualHeight = fHeight;
   1088   return fHeight;
   1089 }
   1090 void CFWL_GridImp::SetAllWidgetsRect() {
   1091   FX_FLOAT fStartLeft = 0;
   1092   int32_t iColumns = m_Columns.GetSize();
   1093   for (int32_t i = 0; i < iColumns; i++) {
   1094     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(m_Columns[i]);
   1095     if (!pColRow) {
   1096       continue;
   1097     }
   1098     pColRow->m_fActualPos = fStartLeft;
   1099     fStartLeft += pColRow->m_fActualSize;
   1100   }
   1101   FX_FLOAT fStartTop = 0;
   1102   int32_t iRows = m_Rows.GetSize();
   1103   for (int32_t j = 0; j < iRows; j++) {
   1104     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(m_Rows[j]);
   1105     if (!pColRow) {
   1106       continue;
   1107     }
   1108     pColRow->m_fActualPos = fStartTop;
   1109     fStartTop += pColRow->m_fActualSize;
   1110   }
   1111   FX_POSITION ps = m_mapWidgetInfo.GetStartPosition();
   1112   while (ps) {
   1113     IFWL_Widget* pWidget = NULL;
   1114     CFWL_GridWidgetInfo* pInfo = NULL;
   1115     m_mapWidgetInfo.GetNextAssoc(ps, (void*&)pWidget, (void*&)pInfo);
   1116     if (!pWidget || !pInfo) {
   1117       continue;
   1118     }
   1119     FX_FLOAT fColumnStart = 0;
   1120     CFWL_GridColRow* pColumn =
   1121         reinterpret_cast<CFWL_GridColRow*>(GetColRow(TRUE, pInfo->m_iColumn));
   1122     if (pColumn) {
   1123       fColumnStart = pColumn->m_fActualPos;
   1124     }
   1125     FX_FLOAT fRowStart = 0;
   1126     CFWL_GridColRow* pRow =
   1127         reinterpret_cast<CFWL_GridColRow*>(GetColRow(FALSE, pInfo->m_iRow));
   1128     if (pRow) {
   1129       fRowStart = pRow->m_fActualPos;
   1130     }
   1131     FX_FLOAT fColumnWidth = 0;
   1132     if (iColumns > 0) {
   1133       for (int32_t j = 0; j < pInfo->m_iColumnSpan; j++) {
   1134         CFWL_GridColRow* pCol = reinterpret_cast<CFWL_GridColRow*>(
   1135             GetColRow(TRUE, pInfo->m_iColumn + j));
   1136         if (!pCol) {
   1137           break;
   1138         }
   1139         fColumnWidth += pCol->m_fActualSize;
   1140       }
   1141     } else {
   1142       fColumnWidth = m_pProperties->m_rtWidget.width;
   1143     }
   1144     FX_FLOAT fRowHeight = 0;
   1145     if (iRows > 0) {
   1146       for (int32_t k = 0; k < pInfo->m_iRowSpan; k++) {
   1147         CFWL_GridColRow* pR = reinterpret_cast<CFWL_GridColRow*>(
   1148             GetColRow(FALSE, pInfo->m_iRow + k));
   1149         if (!pR) {
   1150           break;
   1151         }
   1152         fRowHeight += pR->m_fActualSize;
   1153       }
   1154     } else {
   1155       fRowHeight = m_pProperties->m_rtWidget.height;
   1156     }
   1157     FX_FLOAT fLeftMargin = 0, fRightMargin = 0;
   1158     FX_BOOL bLeftMargin =
   1159         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Left, fLeftMargin);
   1160     FX_BOOL bRightMargin =
   1161         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Right, fRightMargin);
   1162     FX_FLOAT fTopMargin = 0, fBottomMargin = 0;
   1163     FX_BOOL bTopMargin =
   1164         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Top, fTopMargin);
   1165     FX_BOOL bBottomMargin =
   1166         GetWidgetMargin(pWidget, FWL_GRIDMARGIN_Bottom, fBottomMargin);
   1167     FWL_LAYOUTDATA ltd;
   1168     ltd.fWidth = 0;
   1169     ltd.fHeight = 0;
   1170     if (pInfo->m_Size[FWL_GRIDSIZE_Width].eUnit == FWL_GRIDUNIT_Fixed) {
   1171       SetWidgetActualWidth(pInfo, pInfo->m_Size[FWL_GRIDSIZE_Width].fLength);
   1172       ltd.fWidth = pInfo->m_fActualWidth;
   1173     } else {
   1174       if (bLeftMargin && bRightMargin) {
   1175         SetWidgetActualWidth(pInfo, fColumnWidth - fLeftMargin - fRightMargin);
   1176         ltd.fWidth = pInfo->m_fActualWidth;
   1177       } else {
   1178         CFX_RectF rtAuto;
   1179         pWidget->GetWidgetRect(rtAuto, TRUE);
   1180         SetWidgetActualWidth(pInfo, rtAuto.width);
   1181       }
   1182     }
   1183     if (pInfo->m_Size[FWL_GRIDSIZE_Height].eUnit == FWL_GRIDUNIT_Fixed) {
   1184       SetWidgetActualHeight(pInfo, pInfo->m_Size[FWL_GRIDSIZE_Height].fLength);
   1185       ltd.fHeight = pInfo->m_fActualHeight;
   1186     } else {
   1187       if (bTopMargin && bBottomMargin) {
   1188         SetWidgetActualHeight(pInfo, fRowHeight - fTopMargin - fBottomMargin);
   1189         ltd.fHeight = pInfo->m_fActualHeight;
   1190       } else {
   1191         CFX_RectF rtAuto;
   1192         pWidget->GetWidgetRect(rtAuto, TRUE);
   1193         SetWidgetActualHeight(pInfo, rtAuto.height);
   1194       }
   1195     }
   1196     if (bLeftMargin && bRightMargin &&
   1197         pInfo->m_Size[FWL_GRIDSIZE_Width].eUnit == FWL_GRIDUNIT_Fixed) {
   1198       fLeftMargin =
   1199           fColumnStart + fLeftMargin +
   1200           (fColumnWidth - fLeftMargin - fRightMargin - pInfo->m_fActualWidth) /
   1201               2;
   1202     } else if (bLeftMargin) {
   1203       fLeftMargin = fColumnStart + fLeftMargin;
   1204     } else if (bRightMargin) {
   1205       fLeftMargin =
   1206           fColumnStart + fColumnWidth - fRightMargin - pInfo->m_fActualWidth;
   1207     } else {
   1208       fLeftMargin = fColumnStart;
   1209     }
   1210     if (bTopMargin && bBottomMargin &&
   1211         pInfo->m_Size[FWL_GRIDSIZE_Height].eUnit == FWL_GRIDUNIT_Fixed) {
   1212       fTopMargin =
   1213           fRowStart + fTopMargin +
   1214           (fRowHeight - fTopMargin - fBottomMargin - pInfo->m_fActualHeight) /
   1215               2;
   1216     } else if (bTopMargin) {
   1217       fTopMargin = fRowStart + fTopMargin;
   1218     } else if (bBottomMargin) {
   1219       fTopMargin =
   1220           fRowStart + fRowHeight - fBottomMargin - pInfo->m_fActualHeight;
   1221     } else {
   1222       fTopMargin = fRowStart;
   1223     }
   1224     CFX_RectF rtWidget, rtOld;
   1225     rtWidget.Set(fLeftMargin, fTopMargin, pInfo->m_fActualWidth,
   1226                  pInfo->m_fActualHeight);
   1227     pWidget->GetWidgetRect(rtOld);
   1228     if (rtWidget == rtOld) {
   1229       continue;
   1230     }
   1231     pWidget->SetWidgetRect(rtWidget);
   1232     if (rtWidget.width == rtOld.width && rtWidget.height == rtOld.height) {
   1233       continue;
   1234     }
   1235     pWidget->Update();
   1236   }
   1237 }
   1238 FX_BOOL CFWL_GridImp::IsGrid(IFWL_Widget* pWidget) {
   1239   if (!pWidget)
   1240     return FALSE;
   1241   return pWidget->GetClassID() == FWL_CLASSHASH_Grid;
   1242 }
   1243 void CFWL_GridImp::SetSpanAutoColRowSize(const CFX_PtrArray& spanAutos,
   1244                                          FX_FLOAT fTotalSize) {
   1245   int32_t iAutoColRows = spanAutos.GetSize();
   1246   if (iAutoColRows < 1) {
   1247     return;
   1248   }
   1249   CFX_PtrArray autoNoMinMaxs;
   1250   FX_FLOAT fAutoPer = fTotalSize / iAutoColRows;
   1251   for (int32_t j = 0; j < iAutoColRows; j++) {
   1252     CFWL_GridColRow* pColumn = static_cast<CFWL_GridColRow*>(spanAutos[j]);
   1253     FX_FLOAT fOrgSize = pColumn->m_fActualSize;
   1254     if (SetColRowActualSize(pColumn, pColumn->m_fActualSize + fAutoPer, TRUE)) {
   1255       autoNoMinMaxs.Add(pColumn);
   1256     } else {
   1257       fTotalSize -= pColumn->m_fActualSize - fOrgSize;
   1258       int32_t iNoMinMax = iAutoColRows - (j + 1 - autoNoMinMaxs.GetSize());
   1259       if (iNoMinMax > 0 && fTotalSize > 0) {
   1260         fAutoPer = fTotalSize / iNoMinMax;
   1261       } else {
   1262         break;
   1263       }
   1264     }
   1265   }
   1266   int32_t iNormals = autoNoMinMaxs.GetSize();
   1267   if (fTotalSize > 0) {
   1268     if (iNormals == iAutoColRows) {
   1269       fAutoPer = fTotalSize / iNormals;
   1270       for (int32_t k = 0; k < iNormals; k++) {
   1271         CFWL_GridColRow* pColumn =
   1272             static_cast<CFWL_GridColRow*>(autoNoMinMaxs[k]);
   1273         pColumn->m_fActualSize += fAutoPer;
   1274       }
   1275     } else {
   1276       SetSpanAutoColRowSize(autoNoMinMaxs, fTotalSize);
   1277     }
   1278   } else {
   1279   }
   1280 }
   1281 void CFWL_GridImp::SetSpanScaledColRowSize(const CFX_PtrArray& spanScaleds,
   1282                                            FX_FLOAT fTotalSize,
   1283                                            FX_FLOAT fTotalScaledNum) {
   1284   int32_t iScaledColRows = spanScaleds.GetSize();
   1285   if (iScaledColRows < 1) {
   1286     return;
   1287   }
   1288   CFX_PtrArray autoNoMinMaxs;
   1289   FX_FLOAT fPerSize = fTotalSize / fTotalScaledNum;
   1290   for (int32_t i = 0; i < iScaledColRows; i++) {
   1291     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(spanScaleds[i]);
   1292     if (SetColRowActualSize(pColRow, pColRow->m_fActualSize +
   1293                                          fPerSize * pColRow->m_Size.fLength,
   1294                             TRUE)) {
   1295       autoNoMinMaxs.Add(pColRow);
   1296     } else {
   1297       fTotalSize -= pColRow->m_fActualSize;
   1298       fTotalScaledNum -= pColRow->m_Size.fLength;
   1299       int32_t iNoMinMax = iScaledColRows - (i + 1 - autoNoMinMaxs.GetSize());
   1300       if (iNoMinMax > 0 && fTotalSize > 0) {
   1301         fPerSize = fTotalSize / fTotalScaledNum;
   1302       } else {
   1303         break;
   1304       }
   1305     }
   1306   }
   1307   int32_t iNormals = autoNoMinMaxs.GetSize();
   1308   if (fTotalSize > 0) {
   1309     if (iNormals == iScaledColRows) {
   1310       fPerSize = fTotalSize / fTotalScaledNum;
   1311       for (int32_t j = 0; j < iNormals; j++) {
   1312         CFWL_GridColRow* pColumn =
   1313             static_cast<CFWL_GridColRow*>(autoNoMinMaxs[j]);
   1314         pColumn->m_fActualSize += fPerSize * pColumn->m_Size.fLength;
   1315       }
   1316     } else {
   1317       SetSpanScaledColRowSize(autoNoMinMaxs, fTotalSize, fTotalScaledNum);
   1318     }
   1319   } else {
   1320   }
   1321 }
   1322 void CFWL_GridImp::SetScaledColRowsSize(const CFX_PtrArray& spanScaleds,
   1323                                         FX_FLOAT fTotalSize,
   1324                                         FX_FLOAT fTotalScaledNum) {
   1325   int32_t iScaledColRows = spanScaleds.GetSize();
   1326   if (iScaledColRows < 1) {
   1327     return;
   1328   }
   1329   CFX_PtrArray autoNoMinMaxs;
   1330   FX_FLOAT fPerSize = fTotalSize / fTotalScaledNum;
   1331   for (int32_t i = 0; i < iScaledColRows; i++) {
   1332     CFWL_GridColRow* pColRow = static_cast<CFWL_GridColRow*>(spanScaleds[i]);
   1333     if (!pColRow) {
   1334       continue;
   1335     }
   1336     FX_FLOAT fSize = fPerSize * pColRow->m_Size.fLength;
   1337     FX_FLOAT fOrgSize = pColRow->m_fActualSize;
   1338     if (SetColRowActualSize(pColRow, fSize, TRUE)) {
   1339       autoNoMinMaxs.Add(pColRow);
   1340     } else {
   1341       fTotalSize -= pColRow->m_fActualSize - fOrgSize;
   1342       fTotalScaledNum -= pColRow->m_Size.fLength;
   1343       int32_t iNoMinMax = iScaledColRows - (i + 1 - autoNoMinMaxs.GetSize());
   1344       if (iNoMinMax > 0 && fTotalSize > 0) {
   1345         fPerSize = fTotalSize / fTotalScaledNum;
   1346       } else {
   1347         break;
   1348       }
   1349     }
   1350   }
   1351   int32_t iNormals = autoNoMinMaxs.GetSize();
   1352   if (fTotalSize > 0) {
   1353     if (iNormals == iScaledColRows) {
   1354       fPerSize = fTotalSize / fTotalScaledNum;
   1355       for (int32_t i = 0; i < iNormals; i++) {
   1356         CFWL_GridColRow* pColRow =
   1357             static_cast<CFWL_GridColRow*>(autoNoMinMaxs[i]);
   1358         if (!pColRow) {
   1359           continue;
   1360         }
   1361         FX_FLOAT fSize = fPerSize * pColRow->m_Size.fLength;
   1362         pColRow->m_fActualSize = fSize;
   1363       }
   1364     } else {
   1365       SetScaledColRowsSize(autoNoMinMaxs, fTotalSize, fTotalScaledNum);
   1366     }
   1367   } else {
   1368   }
   1369 }
   1370 CFWL_GridImpDelegate::CFWL_GridImpDelegate(CFWL_GridImp* pOwner)
   1371     : m_pOwner(pOwner) {
   1372 }
   1373 int32_t CFWL_GridImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
   1374   if (pMessage->GetClassID() != FWL_MSGHASH_Mouse) {
   1375     return 0;
   1376   }
   1377   CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
   1378   if (pMsg->m_dwCmd != FWL_MSGMOUSECMD_LButtonDown) {
   1379     return 0;
   1380   }
   1381   return 1;
   1382 }
   1383 FWL_ERR CFWL_GridImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
   1384                                            const CFX_Matrix* pMatrix) {
   1385   return m_pOwner->DrawWidget(pGraphics, pMatrix);
   1386 }
   1387