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);
}
Ejemplo n.º 2
0
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)
				));
		}
	}
}