void SResponsiveGridPanel::CacheDesiredSize(float LayoutScaleMultiplier) { // The desired size of the grid is the sum of the desires sizes for every row and column. TArray<float> Columns; TArray<float> Rows; TArray<float> RowToSlot; ComputeDesiredCellSizes(PreviousWidth, Columns, Rows, RowToSlot); TotalDesiredSizes = FVector2D::ZeroVector; if ( Slots.Num() > 0 ) { for ( int ColId = 0; ColId < Columns.Num(); ++ColId ) { TotalDesiredSizes.X += Columns[ColId]; } TotalDesiredSizes.X += ( ColumnGutter * 2 ) * ( TotalColumns - 1 ); for ( int RowId = 0; RowId < Rows.Num(); ++RowId ) { TotalDesiredSizes.Y += Rows[RowId]; } TotalDesiredSizes.Y += ( RowGutter * 2 ) * ( Slots[Slots.Num() - 1].RowParam ); } SPanel::CacheDesiredSize(LayoutScaleMultiplier); }
void SGridPanel::CacheDesiredSize() { // The desired size of the grid is the sum of the desires sizes for every row and column. ComputeDesiredCellSizes( Columns, Rows ); TotalDesiredSizes = FVector2D::ZeroVector; for (int ColId=0; ColId < Columns.Num(); ++ColId) { TotalDesiredSizes.X += Columns[ColId]; } for(int RowId=0; RowId < Rows.Num(); ++RowId) { TotalDesiredSizes.Y += Rows[RowId]; } SPanel::CacheDesiredSize(); }
void SResponsiveGridPanel::OnArrangeChildren( const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren ) const { // Don't attempt to array anything if we don't have any slots allocated. if ( Slots.Num() == 0 ) { return; } // PREPARE PHASE // Prepare some data for arranging children. // FinalColumns will be populated with column sizes that include the stretched column sizes. // Then we will build partial sums so that we can easily handle column spans. const FVector2D LocalSize = AllottedGeometry.GetLocalSize(); FVector2D FlexSpace = LocalSize; PreviousWidth = LocalSize.X; const float FullColumnGutter = (ColumnGutter * 2); const float FullRowGutter = (RowGutter * 2); TArray<float> Rows; TArray<float> RowToSlot; TArray<float> Columns; ComputeDesiredCellSizes(LocalSize.X, Columns, Rows, RowToSlot); check(Rows.Num() == RowToSlot.Num()); TArray<float> FinalColumns; if (Columns.Num() > 0) { FinalColumns.AddUninitialized(Columns.Num()); FinalColumns[FinalColumns.Num() - 1] = 0.0f; // We need an extra cell at the end for easily figuring out the size across any number of cells FinalColumns.AddZeroed((TotalColumns + 1) - Columns.Num()); } // You can't remove the gutter space from the flexspace for the columns because you don't know how // many columns there actually are in a single row at this point float ColumnCoeffTotal = TotalColumns; for (int32 ColIndex = 0; ColIndex < Columns.Num(); ++ColIndex) { // Figure out how big each column needs to be FinalColumns[ColIndex] = (1.0f / ColumnCoeffTotal * FlexSpace.X); } // FinalColumns will be populated with column sizes that include the stretched column sizes. // Then we will build partial sums so that we can easily handle column spans. float RowCoeffTotal = 0.0f; TArray<float> FinalRows; if (Rows.Num() > 0) { FinalRows.AddUninitialized(Rows.Num()); FinalRows[FinalRows.Num() - 1] = 0.0f; // We need an extra cell at the end for easily figuring out the size across any number of cells FinalRows.AddZeroed(1); } FlexSpace.Y -= (RowGutter * 2) * (Slots[Slots.Num() - 1].RowParam); const int32 RowFillCoeffsLength = RowFillCoefficients.Num(); for (int32 RowIndex = 0; RowIndex < Rows.Num(); ++RowIndex) { // Compute the total space available for stretchy rows. if (RowToSlot[RowIndex] >= RowFillCoeffsLength || RowFillCoefficients[RowToSlot[RowIndex]] == 0) { FlexSpace.Y -= Rows[RowIndex]; } else //(RowIndex < RowFillCoeffsLength) { // Compute the denominator for dividing up the stretchy row space RowCoeffTotal += RowFillCoefficients[RowToSlot[RowIndex]]; } } for (int32 RowIndex = 0; RowIndex < Rows.Num(); ++RowIndex) { // Compute how big each row needs to be FinalRows[RowIndex] = (RowToSlot[RowIndex] < RowFillCoeffsLength && RowFillCoefficients[RowToSlot[RowIndex]] != 0) ? (RowFillCoefficients[RowToSlot[RowIndex]] / RowCoeffTotal * FlexSpace.Y) : Rows[RowIndex]; } // Build up partial sums for row and column sizes so that we can handle column and row spans conveniently. ComputePartialSums(FinalColumns); ComputePartialSums(FinalRows); // ARRANGE PHASE int32 ColumnsSoFar = 0; int32 CurrentRow = INDEX_NONE; int32 LastRowParam = INDEX_NONE; float RowGuttersSoFar = 0; for (int32 SlotIndex = 0; SlotIndex < Slots.Num(); ++SlotIndex) { const FSlot& CurSlot = Slots[SlotIndex]; const EVisibility ChildVisibility = CurSlot.GetWidget()->GetVisibility(); if (ChildVisibility != EVisibility::Collapsed) { // Find the appropriate column layout for the slot FSlot::FColumnLayout ColumnLayout; ColumnLayout.Span = TotalColumns; ColumnLayout.Offset = 0; for (int32 Index = CurSlot.ColumnLayouts.Num() - 1; Index >= 0; Index--) { if (CurSlot.ColumnLayouts[Index].LayoutSize < LocalSize.X) { ColumnLayout = CurSlot.ColumnLayouts[Index]; break; } } if (ColumnLayout.Span == 0) { continue; } if (CurSlot.RowParam != LastRowParam) { ColumnsSoFar = 0; LastRowParam = CurSlot.RowParam; ++CurrentRow; if (LastRowParam > 0) { RowGuttersSoFar += FullRowGutter; } } // Figure out the position of this cell. int32 StartColumn = ColumnsSoFar + ColumnLayout.Offset; int32 EndColumn = StartColumn + ColumnLayout.Span; ColumnsSoFar = FMath::Max(EndColumn, ColumnsSoFar); if (ColumnsSoFar > TotalColumns) { StartColumn = 0; EndColumn = StartColumn + ColumnLayout.Span; ColumnsSoFar = EndColumn - StartColumn; ++CurrentRow; } FVector2D ThisCellOffset(FinalColumns[StartColumn], FinalRows[CurrentRow]); // Account for the gutters applied to columns before the starting column of this cell if (StartColumn > 0) { ThisCellOffset.X += FullColumnGutter; } // Figure out the size of this slot; takes row span into account. // We use the properties of partial sums arrays to achieve this. FVector2D CellSize( FinalColumns[EndColumn] - ThisCellOffset.X, FinalRows[CurrentRow + 1] - ThisCellOffset.Y); // Do the standard arrangement of elements within a slot // Takes care of alignment and padding. FMargin SlotPadding(CurSlot.SlotPadding.Get()); AlignmentArrangeResult XAxisResult = AlignChild<Orient_Horizontal>(CellSize.X, CurSlot, SlotPadding); AlignmentArrangeResult YAxisResult = AlignChild<Orient_Vertical>(CellSize.Y, CurSlot, SlotPadding); // The row gutters have already been accounted for in the cell size by removing them from the flexspace, // so we just need to offset the cells appropriately ThisCellOffset.Y += RowGuttersSoFar; // Output the result ArrangedChildren.AddWidget(ChildVisibility, AllottedGeometry.MakeChild( CurSlot.GetWidget(), ThisCellOffset + FVector2D(XAxisResult.Offset, YAxisResult.Offset), FVector2D(XAxisResult.Size, YAxisResult.Size) )); } } }