You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

971 lines
27 KiB
C++

2 years ago
// XTPMarkupGrid.cpp: implementation of the CXTPMarkupGrid class.
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "XTPMarkupObject.h"
#include "XTPMarkupInputElement.h"
#include "XTPMarkupUIElement.h"
#include "XTPMarkupFrameworkElement.h"
#include "XTPMarkupPanel.h"
#include "XTPMarkupGrid.h"
#include "XTPMarkupBuilder.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXTPMarkupDependencyProperty* CXTPMarkupGrid::m_pColumnDefinitionsProperty = NULL;
CXTPMarkupDependencyProperty* CXTPMarkupGrid::m_pRowDefinitionsProperty = NULL;
CXTPMarkupDependencyProperty* CXTPMarkupGrid::m_pColumnProperty = NULL;
CXTPMarkupDependencyProperty* CXTPMarkupGrid::m_pRowProperty = NULL;
CXTPMarkupDependencyProperty* CXTPMarkupGrid::m_pColumnSpanProperty = NULL;
CXTPMarkupDependencyProperty* CXTPMarkupGrid::m_pRowSpanProperty = NULL;
IMPLEMENT_MARKUPCLASS(L"Grid", CXTPMarkupGrid, CXTPMarkupPanel)
void CXTPMarkupGrid::RegisterMarkupClass()
{
m_pColumnDefinitionsProperty = CXTPMarkupDependencyProperty::Register(L"ColumnDefinitions", MARKUP_TYPE(CXTPMarkupColumnDefinitionCollection), MARKUP_TYPE(CXTPMarkupGrid));
m_pRowDefinitionsProperty = CXTPMarkupDependencyProperty::Register(L"RowDefinitions", MARKUP_TYPE(CXTPMarkupRowDefinitionCollection), MARKUP_TYPE(CXTPMarkupGrid));
m_pColumnProperty = CXTPMarkupDependencyProperty::RegisterAttached(L"Column", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupGrid),
new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupGrid::OnCellAttachedPropertyChanged));
m_pRowProperty = CXTPMarkupDependencyProperty::RegisterAttached(L"Row", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupGrid),
new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupGrid::OnCellAttachedPropertyChanged));
m_pColumnSpanProperty = CXTPMarkupDependencyProperty::RegisterAttached(L"ColumnSpan", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupGrid),
new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupGrid::OnCellAttachedPropertyChanged));
m_pRowSpanProperty = CXTPMarkupDependencyProperty::RegisterAttached(L"RowSpan", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupGrid),
new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupGrid::OnCellAttachedPropertyChanged));
}
CXTPMarkupGrid::CXTPMarkupGrid()
{
m_pRowDefinitions = new CXTPMarkupRowDefinitionCollection();
m_pRowDefinitions->SetLogicalParent(this);
m_pColumnDefinitions = new CXTPMarkupColumnDefinitionCollection();
m_pColumnDefinitions->SetLogicalParent(this);
m_pCellCachesCollection = NULL;
m_pDefinitionsU = NULL;
m_pDefinitionsV = NULL;
}
CXTPMarkupGrid::~CXTPMarkupGrid()
{
MARKUP_RELEASE(m_pColumnDefinitions);
MARKUP_RELEASE(m_pRowDefinitions);
SAFE_DELETE_AR(m_pCellCachesCollection);
MARKUP_RELEASE(m_pDefinitionsU);
MARKUP_RELEASE(m_pDefinitionsV);
}
void CXTPMarkupGrid::OnCellAttachedPropertyChanged(CXTPMarkupObject* d, CXTPMarkupPropertyChangedEventArgs* /*e*/)
{
CXTPMarkupUIElement* pVisual = MARKUP_DYNAMICCAST(CXTPMarkupUIElement, d);
if (!pVisual)
return;
CXTPMarkupGrid* pGrid = MARKUP_DYNAMICCAST(CXTPMarkupGrid, pVisual->GetVisualParent());
if (!pGrid)
return;
pGrid->InvalidateMeasure();
}
int CXTPMarkupGrid::GetColumn(CXTPMarkupUIElement* pElement)
{
CXTPMarkupInt* pColumn = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(m_pColumnProperty));
return pColumn != NULL ? (int)*pColumn : 0;
}
int CXTPMarkupGrid::GetRow(CXTPMarkupUIElement* pElement)
{
CXTPMarkupInt* pRow = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(m_pRowProperty));
return pRow != NULL ? (int)*pRow : 0;
}
void CXTPMarkupGrid::SetColumn(CXTPMarkupUIElement* pElement, int nColumn)
{
pElement->SetValue(m_pColumnProperty, new CXTPMarkupInt(nColumn));
}
void CXTPMarkupGrid::SetRow(CXTPMarkupUIElement* pElement, int nRow)
{
pElement->SetValue(m_pRowProperty, new CXTPMarkupInt(nRow));
}
void CXTPMarkupGrid::SetColumnSpan(CXTPMarkupUIElement* pElement, int nColumn)
{
pElement->SetValue(m_pColumnSpanProperty, new CXTPMarkupInt(nColumn));
}
void CXTPMarkupGrid::SetRowSpan(CXTPMarkupUIElement* pElement, int nRow)
{
pElement->SetValue(m_pRowSpanProperty, new CXTPMarkupInt(nRow));
}
int CXTPMarkupGrid::GetColumnSpan(CXTPMarkupUIElement* pElement)
{
CXTPMarkupInt* pColumnSpan = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(m_pColumnSpanProperty));
if (!pColumnSpan)
return 1;
return max(1, (int)*pColumnSpan);
}
int CXTPMarkupGrid::GetRowSpan(CXTPMarkupUIElement* pElement)
{
CXTPMarkupInt* pRowSpan = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(m_pRowSpanProperty));
if (!pRowSpan)
return 1;
return max(1, (int)*pRowSpan);
}
void CXTPMarkupGrid::SetPropertyObject(CXTPMarkupBuilder* pBuilder, CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pValue)
{
if (pProperty == m_pColumnDefinitionsProperty)
{
if (!pValue || !pValue->IsKindOf(MARKUP_TYPE(CXTPMarkupColumnDefinitionCollection)))
{
pBuilder->ThrowBuilderException(_T("CXTPMarkupColumnDefinitionCollection class expected"));
}
MARKUP_RELEASE(m_pColumnDefinitions);
m_pColumnDefinitions = (CXTPMarkupColumnDefinitionCollection*)pValue;
m_pColumnDefinitions->SetLogicalParent(this);
}
else if (pProperty == m_pRowDefinitionsProperty)
{
if (!pValue || !pValue->IsKindOf(MARKUP_TYPE(CXTPMarkupRowDefinitionCollection)))
{
pBuilder->ThrowBuilderException(_T("CXTPMarkupRowDefinitionCollection class expected"));
}
MARKUP_RELEASE(m_pRowDefinitions);
m_pRowDefinitions = (CXTPMarkupRowDefinitionCollection*)pValue;
m_pRowDefinitions->SetLogicalParent(this);
}
else
{
CXTPMarkupPanel::SetPropertyObject(pBuilder, pProperty, pValue);
}
}
AFX_INLINE BOOL IsPositiveInfinity(int size) {
return size > 32000;
}
AFX_INLINE BOOL IsNan(int nSize) {
return nSize == INT_MAX;
}
void CXTPMarkupGrid::ValidateDefinitionsLayout(CXTPMarkupDefinitionCollection* pDefinitions, BOOL bTreatStarAsAuto)
{
for (int i = 0; i < pDefinitions->GetCount(); i++)
{
CXTPMarkupDefinitionBase* pDefinition = pDefinitions->GetItem(i);
pDefinition->OnBeforeLayout();
int nUserMinSize = pDefinition->GetUserMinSize();
int nUserMaxSize = pDefinition->GetUserMaxSize();
int nPositiveInfinity = INT_MAX;
switch (pDefinition->GetUserSize()->GetUnitType())
{
case CXTPMarkupGridLength::unitTypeAuto:
pDefinition->m_nSizeType = sizeTypeAuto;
break;
case CXTPMarkupGridLength::unitTypePixel:
pDefinition->m_nSizeType = sizeTypePixel;
nPositiveInfinity = (int)pDefinition->GetUserSize()->GetValue();
nUserMinSize = max(nUserMinSize, min(nPositiveInfinity, nUserMaxSize));
break;
case CXTPMarkupGridLength::unitTypeStar:
pDefinition->m_nSizeType = bTreatStarAsAuto ? sizeTypeAuto : sizeTypeStar;
break;
}
pDefinition->UpdateMinSize(nUserMinSize);
pDefinition->m_nMeasureSize = max(nUserMinSize, min(nPositiveInfinity, nUserMaxSize));
}
}
int CXTPMarkupGrid::GetLengthTypeForRange(CXTPMarkupDefinitionCollection* pDefinitions, int start, int count)
{
ASSERT(pDefinitions->GetCount() > 0);
int nSizeType = sizeTypeNone;
for (int i = start; i < start + count; i++)
{
nSizeType = (nSizeType | pDefinitions->GetItem(i)->m_nSizeType);
}
return nSizeType;
}
BOOL CXTPMarkupGrid::CELLCACHE::IsStarU() const
{
return nSizeTypeU & CXTPMarkupGrid::sizeTypeStar;
}
BOOL CXTPMarkupGrid::CELLCACHE::IsStarV() const
{
return nSizeTypeV & CXTPMarkupGrid::sizeTypeStar;
}
BOOL CXTPMarkupGrid::CELLCACHE::IsAutoU() const
{
return nSizeTypeU & CXTPMarkupGrid::sizeTypeAuto;
}
BOOL CXTPMarkupGrid::CELLCACHE::IsAutoV() const
{
return nSizeTypeV & CXTPMarkupGrid::sizeTypeAuto;
}
void CXTPMarkupGrid::ValidateCells()
{
SAFE_DELETE_AR(m_pCellCachesCollection);
m_pCellCachesCollection = new CELLCACHE[GetChildren()->GetCount()];
m_nCellGroup[0] = INT_MAX;
m_nCellGroup[1] = INT_MAX;
m_nCellGroup[2] = INT_MAX;
m_nCellGroup[3] = INT_MAX;
BOOL flag = FALSE;
BOOL flag2 = FALSE;
BOOL flag3 = FALSE;
for (int i = GetChildren()->GetCount() - 1; i >= 0; i--)
{
CXTPMarkupUIElement* pElement = GetChildren()->GetItem(i);
if (!pElement)
continue;
CELLCACHE& cache = m_pCellCachesCollection[i];
cache.nColumnIndex = min(GetColumn(pElement), m_pDefinitionsU->GetCount() - 1);
cache.nRowIndex = min(GetRow(pElement), m_pDefinitionsV->GetCount() - 1);
cache.nColumnSpan = min(GetColumnSpan(pElement), m_pDefinitionsU->GetCount() - cache.nColumnIndex);
cache.nRowSpan = min(GetRowSpan(pElement), m_pDefinitionsV->GetCount() - cache.nRowIndex);
cache.nSizeTypeU = GetLengthTypeForRange(m_pDefinitionsU, cache.nColumnIndex, cache.nColumnSpan);
cache.nSizeTypeV = GetLengthTypeForRange(m_pDefinitionsV, cache.nRowIndex, cache.nRowSpan);
flag |= cache.IsStarU();
flag2 |= cache.IsStarV();
if (!cache.IsStarV())
{
if (!cache.IsStarU())
{
cache.nNext = m_nCellGroup[0];
m_nCellGroup[0] = i;
}
else
{
cache.nNext = m_nCellGroup[2];
m_nCellGroup[2] = i;
flag3 |= cache.IsAutoV();
}
}
else if (cache.IsAutoU() && !cache.IsStarU())
{
cache.nNext = m_nCellGroup[1];
m_nCellGroup[1] = i;
}
else
{
cache.nNext = m_nCellGroup[3];
m_nCellGroup[3] = i;
}
}
m_bHasStarCellsU = flag;
m_bHasStarCellsV = flag2;
m_bHasGroup2CellsInAutoRows = flag3;
}
int CXTPMarkupGrid::GetMeasureSizeForRange(CXTPMarkupDefinitionCollection* pDefinitions, int start, int count)
{
double num = 0;
for (int nIndex = start; nIndex < start + count; nIndex++)
{
CXTPMarkupDefinitionBase* pDefinition = pDefinitions->GetItem(nIndex);
num += pDefinition->m_nSizeType == sizeTypeAuto ? pDefinition->m_nMinSize : pDefinition->m_nMeasureSize;
}
return (int)num;
}
void CXTPMarkupGrid::MeasureCell(CXTPMarkupDrawingContext* pDC, int cell, BOOL forceInfinityV)
{
int nPositiveInfinity;
int num2;
if (m_pCellCachesCollection[cell].IsAutoU() && !m_pCellCachesCollection[cell].IsStarU())
{
nPositiveInfinity = INT_MAX;
}
else
{
nPositiveInfinity = GetMeasureSizeForRange(m_pDefinitionsU, m_pCellCachesCollection[cell].nColumnIndex, m_pCellCachesCollection[cell].nColumnSpan);
}
if (forceInfinityV)
{
num2 = INT_MAX;
}
else if (m_pCellCachesCollection[cell].IsAutoV() && !m_pCellCachesCollection[cell].IsStarV())
{
num2 = INT_MAX;
}
else
{
num2 = GetMeasureSizeForRange(m_pDefinitionsV, m_pCellCachesCollection[cell].nRowIndex, m_pCellCachesCollection[cell].nRowSpan);
}
CXTPMarkupUIElement* pElement = GetChildren()->GetItem(cell);
if (pElement != NULL)
{
pElement->Measure(pDC, CSize(nPositiveInfinity, num2));
}
}
void CXTPMarkupGrid::MeasureCellsGroup(CXTPMarkupDrawingContext* pDC, int cellsHead, CSize /*referenceSize*/, BOOL ignoreDesiredSizeU, BOOL forceInfinityV)
{
CArray<SPANKEY, SPANKEY&> arrSpans;
int nCount = GetChildren()->GetCount();
if (cellsHead < nCount)
{
int cell = cellsHead;
do
{
CELLCACHE& cellCache = m_pCellCachesCollection[cell];
MeasureCell(pDC, cell, forceInfinityV);
if (!ignoreDesiredSizeU)
{
if (cellCache.nColumnSpan == 1)
{
m_pDefinitionsU->GetItem(cellCache.nColumnIndex)->UpdateMinSize(GetChildren()->GetItem(cell)->GetDesiredSize().cx);
}
else
{
SPANKEY sk;
sk.nCount = cellCache.nColumnSpan;
sk.nStart = cellCache.nColumnIndex;
sk.nValue = GetChildren()->GetItem(cell)->GetDesiredSize().cx;
sk.bU = TRUE;
arrSpans.Add(sk);
}
}
if (!forceInfinityV)
{
if (cellCache.nRowSpan == 1)
{
m_pDefinitionsV->GetItem(cellCache.nRowIndex)->UpdateMinSize(GetChildren()->GetItem(cell)->GetDesiredSize().cy);
}
else
{
SPANKEY sk;
sk.nCount = cellCache.nRowSpan;
sk.nStart = cellCache.nRowIndex;
sk.nValue = GetChildren()->GetItem(cell)->GetDesiredSize().cy;
sk.bU = FALSE;
arrSpans.Add(sk);
}
}
cell = cellCache.nNext;
}
while (cell < nCount);
}
for (int i = 0; i < (int)arrSpans.GetSize(); i++)
{
const SPANKEY& key = arrSpans[i];
EnsureMinSizeInDefinitionRange(key.bU ? m_pDefinitionsU : m_pDefinitionsV, key.nStart, key.nCount, key.nValue);
}
}
void CXTPMarkupGrid::EnsureMinSizeInDefinitionRange(CXTPMarkupDefinitionCollection* pDefinitions, int start, int count, int requestedSize)
{
if (requestedSize == 0)
return;
CXTPMarkupDefinitionBase** pTempDefinitions = new CXTPMarkupDefinitionBase*[pDefinitions->GetCount()];
int num = start + count;
int nCountAuto = 0;
double dTotalMinSize = 0;
double dTotalPreferedSize = 0;
double dTotalMaxSize = 0;
double dMaxSize = 0;
for (int i = start; i < num; i++)
{
CXTPMarkupDefinitionBase* pDefinition = pDefinitions->GetItem(i);
double minSize = pDefinition->m_nMinSize;
double preferredSize = pDefinition->GetPreferredSize();
double maxSize = IsNan(pDefinition->GetUserMaxSize()) ? minSize : max(minSize, pDefinition->GetUserMaxSize());
dTotalMinSize += minSize;
dTotalPreferedSize += preferredSize;
dTotalMaxSize += maxSize;
pDefinition->m_nSizeCache = maxSize;
if (dMaxSize < maxSize)
{
dMaxSize = maxSize;
}
if (pDefinition->GetUserSize()->IsAuto())
{
nCountAuto++;
}
pTempDefinitions[i - start] = pDefinition;
}
if (requestedSize > dTotalMinSize)
{
if (requestedSize <= dTotalPreferedSize)
{
qsort(pTempDefinitions, count, sizeof(CXTPMarkupDefinitionBase*), SpanPreferredDistributionOrderComparer);
int index = 0;
double d = requestedSize;
while (index < nCountAuto)
{
d -= pTempDefinitions[index]->m_nMinSize;
index++;
}
while (index < count)
{
double a = min(d / ((double) (count - index)), pTempDefinitions[index]->GetPreferredSize());
if (a > pTempDefinitions[index]->m_nMinSize)
{
pTempDefinitions[index]->UpdateMinSize((int)a);
}
d -= a;
index++;
}
}
else if (requestedSize <= dTotalMaxSize)
{
qsort(pTempDefinitions, count, sizeof(CXTPMarkupDefinitionBase*), SpanMaxDistributionOrderComparer);
int n = 0;
double d = requestedSize - dTotalPreferedSize;
while (n < (count - nCountAuto))
{
double num16 = pTempDefinitions[n]->GetPreferredSize();
double num17 = num16 + (d / ((double) ((count - nCountAuto) - n)));
pTempDefinitions[n]->UpdateMinSize((int)min(num17, pTempDefinitions[n]->m_nSizeCache));
d -= pTempDefinitions[n]->m_nMinSize - num16;
n++;
}
while (n < count)
{
double num18 = pTempDefinitions[n]->m_nMinSize;
double num19 = num18 + (d / ((double) (count - n)));
pTempDefinitions[n]->UpdateMinSize((int)(min(num19, pTempDefinitions[n]->m_nSizeCache)));
d -= pTempDefinitions[n]->m_nMinSize - num18;
n++;
}
}
else
{
double dAverage = (double)requestedSize / ((double) count);
if (dAverage < dMaxSize)
{
double num21 = (dMaxSize * count) - dTotalMaxSize;
double num22 = requestedSize - dTotalMaxSize;
for (int j = 0; j < count; j++)
{
double num24 = ((dMaxSize - pTempDefinitions[j]->m_nSizeCache) * num22) / num21;
pTempDefinitions[j]->UpdateMinSize(int(pTempDefinitions[j]->m_nSizeCache + num24));
}
}
else
{
for (int k = 0; k < count; k++)
{
pTempDefinitions[k]->UpdateMinSize((int)dAverage);
}
}
}
}
delete[] pTempDefinitions;
}
void CXTPMarkupGrid::ValidateDefinitions()
{
MARKUP_RELEASE(m_pDefinitionsU);
MARKUP_RELEASE(m_pDefinitionsV);
if (m_pColumnDefinitions->GetCount() == 0)
{
m_pDefinitionsU = new CXTPMarkupColumnDefinitionCollection();
m_pDefinitionsU->Add(new CXTPMarkupColumnDefinition());
}
else
{
m_pDefinitionsU = m_pColumnDefinitions;
m_pDefinitionsU->AddRef();
}
if (m_pRowDefinitions->GetCount() == 0)
{
m_pDefinitionsV = new CXTPMarkupRowDefinitionCollection();
m_pDefinitionsV->Add(new CXTPMarkupRowDefinition());
}
else
{
m_pDefinitionsV = m_pRowDefinitions;
m_pDefinitionsV->AddRef();
}
}
int CXTPMarkupGrid::CalculateDesiredSize(CXTPMarkupDefinitionCollection* pDefinitions)
{
int num = 0;
for (int i = 0; i < pDefinitions->GetCount(); i++)
{
num += pDefinitions->GetItem(i)->m_nMinSize;
}
return num;
}
void CXTPMarkupGrid::ResolveStar(CXTPMarkupDefinitionCollection* pDefinitions, double availableSize)
{
CXTPMarkupDefinitionBase** pTempDefinitions = new CXTPMarkupDefinitionBase*[pDefinitions->GetCount()];
int length = 0;
double num2 = 0;
for (int i = 0; i < pDefinitions->GetCount(); i++)
{
CXTPMarkupDefinitionBase* pDefinition = pDefinitions->GetItem(i);
switch (pDefinition->m_nSizeType)
{
case sizeTypePixel:
num2 += pDefinition->m_nMeasureSize;
continue;
case sizeTypeAuto:
num2 += pDefinition->m_nMinSize;
continue;
case sizeTypeStar:
{
pTempDefinitions[length++] = pDefinition;
double num4 = pDefinition->GetUserSize()->GetValue();
if (num4 != 0)
{
pDefinition->m_nMeasureSize = num4;
double num5 = IsNan(pDefinition->GetUserMaxSize()) ? pDefinition->m_nMinSize : max(pDefinition->m_nMinSize, pDefinition->GetUserMaxSize());
pDefinition->m_nSizeCache = num5 / num4;
}
else
{
pDefinition->m_nMeasureSize = 0;
pDefinition->m_nSizeCache = 0;
}
continue;
}
}
}
if (length > 0)
{
qsort(pTempDefinitions, length, sizeof(CXTPMarkupDefinitionBase*), StarDistributionOrderComparer);
int nIndex;
double num6 = 0;
for (nIndex = length - 1; nIndex >= 0; nIndex--)
{
num6 += pTempDefinitions[nIndex]->m_nMeasureSize;
pTempDefinitions[nIndex]->m_nSizeCache = num6;
}
for (nIndex = 0; nIndex < length; nIndex++)
{
CXTPMarkupDefinitionBase* pDefinition = pTempDefinitions[nIndex];
int nMinSize;
double nMeasureSize = pDefinition->m_nMeasureSize;
if (nMeasureSize == 0)
{
nMinSize = pDefinition->m_nMinSize;
}
else
{
int num10 = (int)(max((double) (availableSize - num2), (double) 0) * (nMeasureSize / pDefinition->m_nSizeCache));
nMinSize = min(num10, pDefinition->GetUserMaxSize());
nMinSize = max(pDefinition->m_nMinSize, nMinSize);
}
pDefinition->m_nMeasureSize = nMinSize;
num2 += nMinSize;
}
}
delete[] pTempDefinitions;
}
CSize CXTPMarkupGrid::MeasureOverride(CXTPMarkupDrawingContext* pDC, CSize constraint)
{
CSize size(0, 0);
if (m_pColumnDefinitions->GetCount() == 0 && m_pRowDefinitions->GetCount() == 0)
{
int nCount = m_pChildren->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPMarkupUIElement* pElement = m_pChildren->GetItem(i);
if (pElement == NULL)
continue;
pElement->Measure(pDC, constraint);
size.cx = max(size.cx, pElement->GetDesiredSize().cx);
size.cy = max(size.cy, pElement->GetDesiredSize().cy);
}
return size;
}
BOOL bTreatStarAsAuto = IsPositiveInfinity(constraint.cx);
BOOL bFlag2 = IsPositiveInfinity(constraint.cy);
ValidateDefinitions();
ValidateDefinitionsLayout(m_pDefinitionsU, bTreatStarAsAuto);
ValidateDefinitionsLayout(m_pDefinitionsV, bFlag2);
ValidateCells();
MeasureCellsGroup(pDC, m_nCellGroup[0], constraint, FALSE, FALSE);
if (!m_bHasGroup2CellsInAutoRows)
{
if (m_bHasStarCellsV)
{
ResolveStar(m_pDefinitionsV, constraint.cy);
}
MeasureCellsGroup(pDC, m_nCellGroup[1], constraint, FALSE, FALSE);
if (m_bHasStarCellsU)
{
ResolveStar(m_pDefinitionsU, constraint.cx);
}
MeasureCellsGroup(pDC, m_nCellGroup[2], constraint, FALSE, FALSE);
}
else if (m_nCellGroup[1] > GetChildren()->GetCount())
{
if (m_bHasStarCellsU)
{
ResolveStar(m_pDefinitionsU, constraint.cx);
}
MeasureCellsGroup(pDC, m_nCellGroup[2], constraint, FALSE, FALSE);
if (m_bHasStarCellsV)
{
ResolveStar(m_pDefinitionsV, constraint.cy);
}
}
else
{
MeasureCellsGroup(pDC, m_nCellGroup[1], constraint, FALSE, TRUE);
if (m_bHasStarCellsU)
{
ResolveStar(m_pDefinitionsU, constraint.cx);
}
MeasureCellsGroup(pDC, m_nCellGroup[2], constraint, FALSE, FALSE);
if (m_bHasStarCellsV)
{
ResolveStar(m_pDefinitionsV, constraint.cy);
}
MeasureCellsGroup(pDC, m_nCellGroup[1], constraint, TRUE, FALSE);
}
MeasureCellsGroup(pDC, m_nCellGroup[3], constraint, FALSE, FALSE);
size = CSize(CalculateDesiredSize(m_pDefinitionsU), CalculateDesiredSize(m_pDefinitionsV));
return size;
}
int _cdecl CXTPMarkupGrid::DistributionOrderComparer(const void *arg1, const void *arg2)
{
CXTPMarkupDefinitionBase* base2 = *((CXTPMarkupDefinitionBase**)arg1);
CXTPMarkupDefinitionBase* base3 = *((CXTPMarkupDefinitionBase**)arg2);
if ((base2->m_nSizeCache - base2->m_nMinSize) == (base3->m_nSizeCache - base3->m_nMinSize))
{
return 0;
}
else if ((base2->m_nSizeCache - base2->m_nMinSize) < (base3->m_nSizeCache - base3->m_nMinSize))
{
return -1;
}
return 1;
};
int _cdecl CXTPMarkupGrid::StarDistributionOrderComparer(const void *arg1, const void *arg2)
{
CXTPMarkupDefinitionBase* base2 = *((CXTPMarkupDefinitionBase**)arg1);
CXTPMarkupDefinitionBase* base3 = *((CXTPMarkupDefinitionBase**)arg2);
if (base2->m_nSizeCache == base3->m_nSizeCache)
{
return 0;
}
else if (base2->m_nSizeCache < base3->m_nSizeCache)
{
return -1;
}
return 1;
};
int _cdecl CXTPMarkupGrid::SpanMaxDistributionOrderComparer(const void *arg1, const void *arg2)
{
CXTPMarkupDefinitionBase* base2 = *((CXTPMarkupDefinitionBase**)arg1);
CXTPMarkupDefinitionBase* base3 = *((CXTPMarkupDefinitionBase**)arg2);
if (base2 == base3)
return 0;
if (base2->GetUserSize()->IsAuto())
{
if (base3->GetUserSize()->IsAuto() && (base2->m_nSizeCache <= base3->m_nSizeCache))
return -1;
return 1;
}
if (base3->GetUserSize()->IsAuto())
{
return -1;
}
if (base2->m_nSizeCache <= base3->m_nSizeCache)
{
return -1;
}
return 1;
};
int _cdecl CXTPMarkupGrid::SpanPreferredDistributionOrderComparer(const void *arg1, const void *arg2)
{
CXTPMarkupDefinitionBase* base2 = *((CXTPMarkupDefinitionBase**)arg1);
CXTPMarkupDefinitionBase* base3 = *((CXTPMarkupDefinitionBase**)arg2);
if (base2 == base3)
return 0;
if (base2->GetUserSize()->IsAuto())
{
if (!base3->GetUserSize()->IsAuto())
return -1;
if (base2->m_nMinSize <= base3->m_nMinSize)
return -1;
return 1;
}
if (!base3->GetUserSize()->IsAuto() && (base2->GetPreferredSize() <= base3->GetPreferredSize()))
{
return -1;
}
return 1;
};
void CXTPMarkupGrid::SetFinalSize(CXTPMarkupDefinitionCollection* pDefinitions, int finalSize)
{
CXTPMarkupDefinitionBase** pTempDefinitions = new CXTPMarkupDefinitionBase*[pDefinitions->GetCount()];
int length = 0;
int num2 = pDefinitions->GetCount();
double num3 = 0;
for (int i = 0; i < pDefinitions->GetCount(); i++)
{
CXTPMarkupDefinitionBase* pDefinition = pDefinitions->GetItem(i);
if (pDefinition->GetUserSize()->IsStar())
{
pTempDefinitions[length++] = pDefinition;
double d = pDefinition->GetUserSize()->GetValue();
if (d == 0)
{
pDefinition->m_nMeasureSize = 0;
pDefinition->m_nSizeCache = 0;
}
else
{
pDefinition->m_nMeasureSize = d;
int num6 = IsNan(pDefinition->GetUserMaxSize()) ? pDefinition->m_nMinSize : max(pDefinition->m_nMinSize, pDefinition->GetUserMaxSize());
pDefinition->m_nSizeCache = (double)num6 / (double)d;
}
}
else
{
pTempDefinitions[--num2] = pDefinition;
double nMinSizeForArrange = 0;
switch (pDefinition->GetUserSize()->GetUnitType())
{
case CXTPMarkupGridLength::unitTypeAuto:
nMinSizeForArrange = pDefinition->m_nMinSize;
break;
case CXTPMarkupGridLength::unitTypePixel:
nMinSizeForArrange = pDefinition->GetUserSize()->GetValue();
break;
}
int nUserMaxSize = pDefinition->GetUserMaxSize();
pDefinition->m_nSizeCache = max(pDefinition->m_nMinSize, min(nMinSizeForArrange, nUserMaxSize));
num3 += pDefinition->m_nSizeCache;
}
}
if (length > 0)
{
qsort(pTempDefinitions, length, sizeof(CXTPMarkupDefinitionBase*), StarDistributionOrderComparer);
double num9 = 0;
int nIndex;
for (nIndex = length - 1; nIndex >= 0; nIndex--)
{
num9 += pTempDefinitions[nIndex]->m_nMeasureSize;
pTempDefinitions[nIndex]->m_nSizeCache = num9;
}
for (nIndex = 0; nIndex < length; nIndex++)
{
CXTPMarkupDefinitionBase* pDefinition = pTempDefinitions[nIndex];
int num11;
double nMeasureSize = pDefinition->m_nMeasureSize;
if (nMeasureSize == 0)
{
num11 = pDefinition->m_nMinSize;
}
else
{
double num13 = max((double) (finalSize - num3), (double) 0) * (nMeasureSize / pDefinition->m_nSizeCache);
num11 = min((int)num13, pDefinition->GetUserMaxSize());
num11 = max(pDefinition->m_nMinSize, num11);
}
pDefinition->m_nSizeCache = num11;
num3 += num11;
}
}
if (num3 > finalSize)
{
qsort(pTempDefinitions, length, sizeof(CXTPMarkupDefinitionBase*), DistributionOrderComparer);
double num14 = finalSize - num3;
for (int k = 0; k < pDefinitions->GetCount(); k++)
{
double num16 = pTempDefinitions[k]->m_nSizeCache + (num14 / ((double) (pDefinitions->GetCount() - k)));
num16 = min(max(num16, pTempDefinitions[k]->m_nMinSize), pTempDefinitions[k]->m_nSizeCache);
num14 -= num16 - pTempDefinitions[k]->m_nSizeCache;
pTempDefinitions[k]->m_nSizeCache = num16;
}
}
pDefinitions->GetItem(0)->m_nFinalOffset = 0;
for (int j = 1; j < pDefinitions->GetCount(); j++)
{
pDefinitions->GetItem(j)->m_nFinalOffset = pDefinitions->GetItem(j - 1)->m_nFinalOffset + (int)pDefinitions->GetItem(j - 1)->m_nSizeCache;
}
delete[] pTempDefinitions;
}
int CXTPMarkupGrid::GetFinalSizeForRange(CXTPMarkupDefinitionCollection* pDefinitions, int start, int count)
{
int num = 0;
for (int nIndex = start; nIndex < start + count; nIndex++)
{
num += (int)pDefinitions->GetItem(nIndex)->m_nSizeCache;
}
return num;
}
CSize CXTPMarkupGrid::ArrangeOverride(CSize arrangeSize)
{
if ((m_pColumnDefinitions->GetCount() == 0 && m_pRowDefinitions->GetCount() == 0) || (m_pCellCachesCollection == NULL))
{
int nCount = m_pChildren->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPMarkupUIElement* pElement = m_pChildren->GetItem(i);
if (pElement == NULL)
continue;
pElement->Arrange(CRect(0, 0, arrangeSize.cx, arrangeSize.cy));
}
return arrangeSize;
}
SetFinalSize(m_pDefinitionsU, arrangeSize.cx);
SetFinalSize(m_pDefinitionsV, arrangeSize.cy);
int nCount = m_pChildren->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPMarkupUIElement* pElement = m_pChildren->GetItem(i);
if (pElement == NULL)
continue;
CELLCACHE& cellCache = m_pCellCachesCollection[i];
int columnIndex = cellCache.nColumnIndex;
int rowIndex = cellCache.nRowIndex;
int columnSpan = cellCache.nColumnSpan;
int rowSpan = cellCache.nRowSpan;
CRect finalRect(CPoint(m_pDefinitionsU->GetItem(columnIndex)->m_nFinalOffset,
m_pDefinitionsV->GetItem(rowIndex)->m_nFinalOffset),
CSize(GetFinalSizeForRange(m_pDefinitionsU, columnIndex, columnSpan),
GetFinalSizeForRange(m_pDefinitionsV, rowIndex, rowSpan)));
pElement->Arrange(finalRect);
}
return arrangeSize;
}