#include "stdafx.h" #include "TileBox.h" namespace ui { TileLayout::TileLayout() : m_nColumns(1), m_szItem(0, 0) { } CSize TileLayout::ArrangeChild(const std::vector& items, UiRect rc) { // Position the elements if( m_szItem.cx > 0 ) m_nColumns = (rc.right - rc.left) / m_szItem.cx; if( m_nColumns == 0 ) m_nColumns = 1; int cyNeeded = 0; int cxWidth = rc.GetWidth() / m_nColumns; int deviation = rc.GetWidth() - cxWidth * m_nColumns; int tmpDeviation = deviation; int cyHeight = 0; int iCount = 0; CPoint ptTile(rc.left, rc.top); int iPosX = rc.left; for( auto it = items.begin(); it != items.end(); it++ ) { auto pControl = *it; if( !pControl->IsVisible() ) continue; if( pControl->IsFloat() ) { SetFloatPos(pControl, rc); continue; } // Determine size UiRect rcTile(ptTile.x, ptTile.y, ptTile.x + cxWidth, ptTile.y); if (tmpDeviation > 0) { rcTile.right += 1; tmpDeviation--; } if( (iCount % m_nColumns) == 0 ) { int iIndex = iCount; for (auto it2 = it; it2 != items.end(); it2++) { auto pLineControl = *it2; if( !pLineControl->IsVisible() ) continue; if( pLineControl->IsFloat() ) continue; UiRect rcMargin = pLineControl->GetMargin(); CSize szAvailable(rcTile.right - rcTile.left - rcMargin.left - rcMargin.right, 9999); if( iIndex == iCount || (iIndex + 1) % m_nColumns == 0 ) { szAvailable.cx -= m_iChildMargin / 2; } else { szAvailable.cx -= m_iChildMargin; } if( szAvailable.cx < pControl->GetMinWidth() ) szAvailable.cx = pControl->GetMinWidth(); if( pControl->GetMaxWidth() >= 0 && szAvailable.cx > pControl->GetMaxWidth() ) szAvailable.cx = pControl->GetMaxWidth(); CSize szTile = pLineControl->EstimateSize(szAvailable); if( szTile.cx < pControl->GetMinWidth() ) szTile.cx = pControl->GetMinWidth(); if( pControl->GetMaxWidth() >= 0 && szTile.cx > pControl->GetMaxWidth() ) szTile.cx = pControl->GetMaxWidth(); if( szTile.cy < pControl->GetMinHeight() ) szTile.cy = pControl->GetMinHeight(); if( szTile.cy > pControl->GetMaxHeight() ) szTile.cy = pControl->GetMaxHeight(); cyHeight = MAX(cyHeight, szTile.cy + rcMargin.top + rcMargin.bottom); if( (++iIndex % m_nColumns) == 0) break; } } UiRect rcMargin = pControl->GetMargin(); UiRect newRcTile = rcTile; newRcTile.left += rcMargin.left + m_iChildMargin / 2; newRcTile.right -= rcMargin.right + m_iChildMargin / 2; // Set position newRcTile.top = ptTile.y + rcMargin.top; newRcTile.bottom = ptTile.y + cyHeight; CSize szAvailable(newRcTile.right - newRcTile.left, newRcTile.bottom - newRcTile.top); CSize szTile = pControl->EstimateSize(szAvailable); if( szTile.cx == DUI_LENGTH_STRETCH ) szTile.cx = szAvailable.cx; if( szTile.cy == DUI_LENGTH_STRETCH ) szTile.cy = szAvailable.cy; if( szTile.cx < pControl->GetMinWidth() ) szTile.cx = pControl->GetMinWidth(); if( pControl->GetMaxWidth() >= 0 && szTile.cx > pControl->GetMaxWidth() ) szTile.cx = pControl->GetMaxWidth(); if( szTile.cy < pControl->GetMinHeight() ) szTile.cy = pControl->GetMinHeight(); if( szTile.cy > pControl->GetMaxHeight() ) szTile.cy = pControl->GetMaxHeight(); UiRect rcPos((newRcTile.left + newRcTile.right - szTile.cx) / 2, (newRcTile.top + newRcTile.bottom - szTile.cy) / 2, (newRcTile.left + newRcTile.right - szTile.cx) / 2 + szTile.cx, (newRcTile.top + newRcTile.bottom - szTile.cy) / 2 + szTile.cy); pControl->SetPos(rcPos); if( (++iCount % m_nColumns) == 0 ) { ptTile.x = iPosX; ptTile.y += cyHeight + m_iChildMargin; cyHeight = 0; tmpDeviation = deviation; } else { ptTile.x += rcTile.GetWidth(); } cyNeeded = newRcTile.bottom - rc.top; } CSize size(rc.right - rc.left, cyNeeded); return size; } CSize TileLayout::AjustSizeByChild(const std::vector& items, CSize szAvailable) { CSize size = m_pOwner->Control::EstimateSize(szAvailable); size.cy = 0; if( m_szItem.cx > 0 ) m_nColumns = m_pOwner->GetFixedWidth() / m_szItem.cx; if( m_nColumns == 0 ) m_nColumns = 1; int visibleCount = (int)items.size(); for (auto it = items.begin(); it != items.end(); it++) { if (!(*it)->IsVisible()) { visibleCount--; } } int rows = visibleCount / m_nColumns; if (visibleCount % m_nColumns != 0) { rows += 1; } if (visibleCount > 0) { int childMarginTotal; if (visibleCount % m_nColumns == 0) { childMarginTotal = (visibleCount / m_nColumns - 1) * m_iChildMargin; } else { childMarginTotal = (visibleCount / m_nColumns) * m_iChildMargin; } Control* pControl = static_cast(items[0]); size.cy += pControl->GetFixedHeight() * rows + m_rcPadding.top + m_rcPadding.bottom + childMarginTotal; } return size; } bool TileLayout::SetAttribute(const std::wstring& strName, const std::wstring& strValue) { bool hasAttribute = true; if( strName == _T("itemsize") ) { CSize szItem; LPTSTR pstr = NULL; szItem.cx = _tcstol(strValue.c_str(), &pstr, 10); ASSERT(pstr); szItem.cy = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr); SetItemSize(szItem); } else if( strName == _T("columns")) { SetColumns(_ttoi(strValue.c_str())); } else { hasAttribute = Layout::SetAttribute(strName, strValue); } return hasAttribute; } CSize TileLayout::GetItemSize() const { return m_szItem; } void TileLayout::SetItemSize(CSize szItem) { DpiManager::GetInstance()->ScaleSize(szItem); if( m_szItem.cx != szItem.cx || m_szItem.cy != szItem.cy ) { m_szItem = szItem; m_pOwner->Arrange(); } } int TileLayout::GetColumns() const { return m_nColumns; } void TileLayout::SetColumns(int nCols) { if( nCols <= 0 ) return; m_nColumns = nCols; m_pOwner->Arrange(); } TileBox::TileBox() : Box(new TileLayout()) { } }