nim_duilib/duilib/Box/TileBox.cpp

195 lines
5.6 KiB
C++
Raw Normal View History

2019-04-19 17:19:57 +08:00
#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())
{
}
}