195 lines
5.6 KiB
C++
195 lines
5.6 KiB
C++
![]() |
#include "stdafx.h"
|
||
|
#include "TileBox.h"
|
||
|
|
||
|
namespace ui
|
||
|
{
|
||
|
|
||
|
TileLayout::TileLayout() : m_nColumns(1), m_szItem(0, 0)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
CSize TileLayout::ArrangeChild(const std::vector<Control*>& 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<Control*>& 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<Control*>(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())
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|