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
16IFWL_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}
23IFWL_Grid::IFWL_Grid() {}
24FWL_HGRIDCOLROW IFWL_Grid::InsertColRow(FX_BOOL bColumn, int32_t nIndex) {
25  return static_cast<CFWL_GridImp*>(GetImpl())->InsertColRow(bColumn, nIndex);
26}
27int32_t IFWL_Grid::CountColRows(FX_BOOL bColumn) {
28  return static_cast<CFWL_GridImp*>(GetImpl())->CountColRows(bColumn);
29}
30FWL_HGRIDCOLROW IFWL_Grid::GetColRow(FX_BOOL bColumn, int32_t nIndex) {
31  return static_cast<CFWL_GridImp*>(GetImpl())->GetColRow(bColumn, nIndex);
32}
33int32_t IFWL_Grid::GetIndex(FWL_HGRIDCOLROW hColRow) {
34  return static_cast<CFWL_GridImp*>(GetImpl())->GetIndex(hColRow);
35}
36FX_FLOAT IFWL_Grid::GetSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit) {
37  return static_cast<CFWL_GridImp*>(GetImpl())->GetSize(hColRow, eUnit);
38}
39FWL_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}
44FX_FLOAT IFWL_Grid::GetMinSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit) {
45  return static_cast<CFWL_GridImp*>(GetImpl())->GetMinSize(hColRow, eUnit);
46}
47FWL_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}
53FX_FLOAT IFWL_Grid::GetMaxSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit) {
54  return static_cast<CFWL_GridImp*>(GetImpl())->GetMaxSize(hColRow, eUnit);
55}
56FWL_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}
62FX_BOOL IFWL_Grid::DeleteColRow(FWL_HGRIDCOLROW hColRow) {
63  return static_cast<CFWL_GridImp*>(GetImpl())->DeleteColRow(hColRow);
64}
65FX_BOOL IFWL_Grid::IsColumn(FWL_HGRIDCOLROW hColRow) {
66  return static_cast<CFWL_GridImp*>(GetImpl())->IsColumn(hColRow);
67}
68int32_t IFWL_Grid::GetWidgetPos(IFWL_Widget* pWidget, FX_BOOL bColumn) {
69  return static_cast<CFWL_GridImp*>(GetImpl())->GetWidgetPos(pWidget, bColumn);
70}
71FWL_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}
77int32_t IFWL_Grid::GetWidgetSpan(IFWL_Widget* pWidget, FX_BOOL bColumn) {
78  return static_cast<CFWL_GridImp*>(GetImpl())->GetWidgetSpan(pWidget, bColumn);
79}
80FWL_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}
86FX_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}
92FWL_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}
99FX_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}
105FWL_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}
111FWL_ERR IFWL_Grid::RemoveWidgetMargin(IFWL_Widget* pWidget,
112                                      FWL_GRIDMARGIN eMargin) {
113  return static_cast<CFWL_GridImp*>(GetImpl())
114      ->RemoveWidgetMargin(pWidget, eMargin);
115}
116FX_FLOAT IFWL_Grid::GetGridSize(FWL_GRIDSIZE eSize, FWL_GRIDUNIT& eUnit) {
117  return static_cast<CFWL_GridImp*>(GetImpl())->GetGridSize(eSize, eUnit);
118}
119FWL_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
125CFWL_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}
141CFWL_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}
163FWL_ERR CFWL_GridImp::GetClassName(CFX_WideString& wsClass) const {
164  wsClass = FWL_CLASS_Grid;
165  return FWL_ERR_Succeeded;
166}
167FX_DWORD CFWL_GridImp::GetClassID() const {
168  return FWL_CLASSHASH_Grid;
169}
170FWL_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}
176FWL_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}
183FWL_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}
194FWL_ERR CFWL_GridImp::SetWidgetRect(const CFX_RectF& rect) {
195  CFWL_WidgetImp::SetWidgetRect(rect);
196  return FWL_ERR_Succeeded;
197}
198FWL_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}
207FWL_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}
251FWL_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}
262FWL_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}
275FWL_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}
291int32_t CFWL_GridImp::CountColRows(FX_BOOL bColumn) {
292  if (bColumn) {
293    return m_Columns.GetSize();
294  }
295  return m_Rows.GetSize();
296}
297FWL_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}
309int32_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}
315FX_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}
322FWL_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}
332FX_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}
340FWL_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}
350FX_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}
358FWL_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}
368FX_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}
383FX_BOOL CFWL_GridImp::IsColumn(FWL_HGRIDCOLROW hColRow) {
384  return m_Columns.Find(hColRow) != -1;
385}
386int32_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}
394FWL_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}
404int32_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}
412FWL_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}
422FX_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}
433FWL_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}
445FX_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}
456FWL_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}
467FWL_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}
476FX_FLOAT CFWL_GridImp::GetGridSize(FWL_GRIDSIZE eSize, FWL_GRIDUNIT& eUnit) {
477  eUnit = m_Size[eSize].eUnit;
478  return m_Size[eSize].fLength;
479}
480FWL_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}
487CFWL_GridWidgetInfo* CFWL_GridImp::GetWidgetInfo(IFWL_Widget* pWidget) {
488  return static_cast<CFWL_GridWidgetInfo*>(m_mapWidgetInfo.GetValueAt(pWidget));
489}
490void 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}
513void 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}
547void 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}
555void 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}
577void 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}
599FX_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}
623FX_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}
646FX_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}
730FX_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}
816FX_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}
929FX_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}
1045FX_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}
1064FX_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}
1077FX_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}
1090void 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}
1238FX_BOOL CFWL_GridImp::IsGrid(IFWL_Widget* pWidget) {
1239  if (!pWidget)
1240    return FALSE;
1241  return pWidget->GetClassID() == FWL_CLASSHASH_Grid;
1242}
1243void 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}
1281void 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}
1322void 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}
1370CFWL_GridImpDelegate::CFWL_GridImpDelegate(CFWL_GridImp* pOwner)
1371    : m_pOwner(pOwner) {
1372}
1373int32_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}
1383FWL_ERR CFWL_GridImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
1384                                           const CFX_Matrix* pMatrix) {
1385  return m_pOwner->DrawWidget(pGraphics, pMatrix);
1386}
1387