// 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 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; }