void HKWidgetListbox::ArrangeChildren() { // early out? int numChildren = GetNumChildren(); if(numChildren == 0) return; MFVector pPos = orientation == Horizontal ? MakeVector(padding.x + scrollOffset, padding.y) : MakeVector(padding.x, padding.y + scrollOffset); MFVector pSize = MakeVector(size.x - (padding.x + padding.z), size.y - (padding.y + padding.w)); contentSize = 0.f; for(int a=0; a<numChildren; ++a) { HKWidget *pWidget = GetChild(a); if(pWidget->GetVisible() == Gone) continue; const MFVector &cMargin = pWidget->GetLayoutMargin(); const MFVector &cSize = pWidget->GetSize(); MFVector tPos = pPos + MakeVector(cMargin.x, cMargin.y); MFVector tSize = MFMax(pSize - MakeVector(cMargin.x + cMargin.z, cMargin.y + cMargin.w), MFVector::zero); if(orientation == Horizontal) { float itemSize = cSize.x + cMargin.x + cMargin.z; contentSize += itemSize; pPos.x += itemSize; pWidget->SetPosition(tPos); pWidget->SetHeight(tSize.y); } else { float itemSize = cSize.y + cMargin.y + cMargin.w; contentSize += itemSize; pPos.y += itemSize; pWidget->SetPosition(tPos); pWidget->SetWidth(tSize.x); } } }
void HKWidgetLayoutLinear::ArrangeChildren() { bool bFitWidth = bAutoWidth && GetHAlign() != Align_Fill; // fitFlags & FitContentHorizontal bool bFitHeight = bAutoHeight && GetVAlign() != VAlign_Fill; // fitFlags & FitContentVertical // early out? int numChildren = GetNumChildren(); if(numChildren == 0) { if(bFitWidth || bFitHeight) { // resize the layout MFVector newSize = GetSize(); if(bFitWidth) newSize.x = padding.x + padding.z; if(bFitHeight) newSize.y = padding.y + padding.w; Resize(newSize); } return; } // calculate weight and fit float totalWeight = 0.f; MFVector fit = MakeVector(padding.x + padding.z, padding.y + padding.w); for(int a=0; a<numChildren; ++a) { HKWidget *pWidget = GetChild(a); if(pWidget->GetVisible() == Gone) continue; const MFVector &cSize = pWidget->GetSizeWithMargin(); if(orientation == Horizontal) { if(pWidget->GetHAlign() == Align_Fill) // fill horizontally totalWeight += pWidget->GetLayoutWeight(); else fit.x += cSize.x; fit.y = MFMax(fit.y, cSize.y + padding.y + padding.w); } else { if(pWidget->GetVAlign() == VAlign_Fill) // fill vertically totalWeight += pWidget->GetLayoutWeight(); else fit.y += cSize.y; fit.x = MFMax(fit.x, cSize.x + padding.x + padding.z); } } if(bFitWidth || bFitHeight) { // resize the layout MFVector newSize = size; if(bFitWidth) newSize.x = fit.x; if(bFitHeight) newSize.y = fit.y; Resize(newSize); } MFVector pPos = MakeVector(padding.x, padding.y); MFVector pSize = MakeVector(size.x - (padding.x + padding.z), size.y - (padding.y + padding.w)); MFVector slack = MFMax(size - fit, MFVector::zero); for(int a=0; a<numChildren; ++a) { HKWidget *pWidget = GetChild(a); if(pWidget->GetVisible() == Gone) continue; const MFVector &cMargin = pWidget->GetLayoutMargin(); const MFVector &cSize = pWidget->GetSize(); MFVector tPos = pPos + MakeVector(cMargin.x, cMargin.y); MFVector tSize = MFMax(pSize - MakeVector(cMargin.x + cMargin.z, cMargin.y + cMargin.w), MFVector::zero); Align align = pWidget->GetHAlign(); VAlign valign = pWidget->GetVAlign(); MFVector newSize = cSize; if(orientation == Horizontal) { if(align == Align_Fill) // fill horizontally { // this widget fills available empty space in the parent container newSize.x = slack.x * (pWidget->GetLayoutWeight() / totalWeight); pPos.x += newSize.x; newSize.x = MFMax(0.f, newSize.x - cMargin.x - cMargin.z); } else { pPos.x += cSize.x + cMargin.x + cMargin.z; } switch(valign) { case VAlign_None: case VAlign_Top: pWidget->SetPosition(tPos); break; case VAlign_Center: pWidget->SetPosition(tPos + MakeVector(0, MFMax(tSize.y - cSize.y, 0.f) * 0.5f)); break; case VAlign_Bottom: pWidget->SetPosition(tPos + MakeVector(0, MFMax(tSize.y - cSize.y, 0.f))); break; case VAlign_Fill: pWidget->SetPosition(tPos); newSize.y = tSize.y; break; default: MFUNREACHABLE; } } else { if(valign == VAlign_Fill) // fill vertically { // this widget fills available empty space in the parent container newSize.y = slack.y * (pWidget->GetLayoutWeight() / totalWeight); pPos.y += newSize.y; newSize.y = MFMax(0.f, newSize.y - cMargin.y - cMargin.w); } else { pPos.y += cSize.y + cMargin.y + cMargin.w; } switch(align) { case Align_None: case Align_Left: pWidget->SetPosition(tPos); break; case Align_Center: pWidget->SetPosition(tPos + MakeVector(MFMax(tSize.x - cSize.x, 0.f) * 0.5f, 0)); break; case Align_Right: pWidget->SetPosition(tPos + MakeVector(MFMax(tSize.x - cSize.x, 0.f), 0)); break; case Align_Fill: pWidget->SetPosition(tPos); newSize.x = tSize.x; break; default: MFUNREACHABLE; } } ResizeChild(pWidget, newSize); } }
void HKWidgetLayoutFrame::ArrangeChildren() { bool bFitWidth = bAutoWidth && GetHAlign() != Align_Fill; // fitFlags & FitContentHorizontal bool bFitHeight = bAutoHeight && GetVAlign() != VAlign_Fill; // fitFlags & FitContentVertical // early out? int numChildren = GetNumChildren(); if(numChildren == 0) { if(bFitWidth || bFitHeight) { // resize the layout MFVector newSize = GetSize(); if(bFitWidth) newSize.x = padding.x + padding.z; if(bFitHeight) newSize.y = padding.y + padding.w; Resize(newSize); } return; } if(bFitWidth || bFitHeight) { // fit to largest child in each dimension MFVector fit = MFVector::zero; for(int a=0; a<numChildren; ++a) { HKWidget *pWidget = GetChild(a); const MFVector &cSize = pWidget->GetSizeWithMargin(); fit.x = MFMax(fit.x, cSize.x + padding.x + padding.z); fit.y = MFMax(fit.y, cSize.y + padding.y + padding.w); } // resize the layout MFVector newSize = GetSize(); if(bFitWidth) newSize.x = fit.x; if(bFitHeight) newSize.y = fit.y; Resize(newSize); } MFVector cPos = MakeVector(padding.x, padding.y); MFVector cSize = MakeVector(size.x - (padding.x + padding.z), size.y - (padding.y + padding.w)); for(int a=0; a<numChildren; ++a) { HKWidget *pWidget = GetChild(a); const MFVector &cMargin = pWidget->GetLayoutMargin(); const MFVector &size = pWidget->GetSize(); MFVector tPos = cPos + MakeVector(cMargin.x, cMargin.y); MFVector tSize = cSize - MakeVector(cMargin.x + cMargin.z, cMargin.y + cMargin.w); switch(pWidget->GetLayoutJustification()) { case TopLeft: pWidget->SetPosition(tPos); break; case TopCenter: pWidget->SetPosition(tPos + MakeVector((tSize.x - size.x) * 0.5f, 0)); break; case TopRight: pWidget->SetPosition(tPos + MakeVector(tSize.x - size.x, 0)); break; case TopFill: pWidget->SetPosition(tPos); ResizeChild(pWidget, MakeVector(tSize.x, size.y)); break; case CenterLeft: pWidget->SetPosition(tPos + MakeVector(0, (tSize.y - size.y) * 0.5f)); break; case Center: pWidget->SetPosition(tPos + MakeVector((tSize.x - size.x) * 0.5f, (tSize.y - size.y) * 0.5f)); break; case CenterRight: pWidget->SetPosition(tPos + MakeVector(tSize.x - size.x, (tSize.y - size.y) * 0.5f)); break; case CenterFill: pWidget->SetPosition(tPos + MakeVector(0, (tSize.y - size.y) * 0.5f)); ResizeChild(pWidget, MakeVector(tSize.x, size.y)); break; case BottomLeft: pWidget->SetPosition(tPos + MakeVector(0, tSize.y - size.y)); break; case BottomCenter: pWidget->SetPosition(tPos + MakeVector((tSize.x - size.x) * 0.5f, tSize.y - size.y)); break; case BottomRight: pWidget->SetPosition(tPos + MakeVector(tSize.x - size.x, tSize.y - size.y)); break; case BottomFill: pWidget->SetPosition(tPos + MakeVector(0, tSize.y - size.y)); ResizeChild(pWidget, MakeVector(tSize.x, size.y)); break; case FillLeft: pWidget->SetPosition(tPos); ResizeChild(pWidget, MakeVector(size.x, tSize.y)); break; case FillCenter: pWidget->SetPosition(tPos + MakeVector((tSize.x - size.x) * 0.5f, 0)); ResizeChild(pWidget, MakeVector(size.x, tSize.y)); break; case FillRight: pWidget->SetPosition(tPos + MakeVector(tSize.x - size.x, 0)); ResizeChild(pWidget, MakeVector(size.x, tSize.y)); break; case Fill: pWidget->SetPosition(tPos); ResizeChild(pWidget, tSize); break; case None: // this widget has absolute coordinates.. default: break; } } }