int32 SSplitter::GetHandleBeingResizedFromMousePosition( float PhysicalSplitterHandleSize, float HitDetectionSplitterHandleSize, FVector2D LocalMousePos, const TArray<FLayoutGeometry>& ChildGeometries )
{
	const int32 AxisIndex = (SplitterOrientation == Orient_Horizontal) ? 0 : 1;
	const float HalfHitDetectionSplitterHandleSize = ( HitDetectionSplitterHandleSize / 2 );
	const float HalfPhysicalSplitterHandleSize = ( PhysicalSplitterHandleSize / 2 );

	// Search for the two widgets between which the cursor currently resides.
	for ( int32 ChildIndex = 1; ChildIndex < ChildGeometries.Num(); ++ChildIndex )
	{
		FSlateRect PrevChildRect = ChildGeometries[ChildIndex - 1].GetRectInParentSpace();
		FVector2D NextChildOffset = ChildGeometries[ChildIndex].GetOffsetInParentSpace();
		float PrevBound = PrevChildRect.GetTopLeft().Component(AxisIndex) + PrevChildRect.GetSize().Component(AxisIndex) - HalfHitDetectionSplitterHandleSize + HalfPhysicalSplitterHandleSize;
		float NextBound = NextChildOffset.Component(AxisIndex) + HalfHitDetectionSplitterHandleSize - HalfPhysicalSplitterHandleSize;

		if ( LocalMousePos.Component(AxisIndex) > PrevBound && LocalMousePos.Component(AxisIndex) < NextBound )
		{
			return ChildIndex - 1;
		}
	}

	return INDEX_NONE;
}
void SSplitter::HandleResizing( const float PhysicalSplitterHandleSize, const ESplitterResizeMode::Type ResizeMode, int32 DraggedHandle, const FVector2D& LocalMousePos, TPanelChildren<FSlot>& Children, const TArray<FLayoutGeometry>& ChildGeometries )
{
	const int32 NumChildren = Children.Num();

	const int32 AxisIndex = (SplitterOrientation == Orient_Horizontal) ? 0 : 1;

	// Note:
	//  - Prev vs. Next refers to the widgets in the order they are laid out (left->right, top->bottom).
	//  - New vs. Old refers to the Old values for width/height vs. the post-resize values.

	const float HandlePos = ChildGeometries[DraggedHandle+1].GetLocalToParentTransform().GetTranslation().Component(AxisIndex) - PhysicalSplitterHandleSize / 2;
	float Delta = LocalMousePos.Component(AxisIndex) - HandlePos;

	const int32 SlotBeforeDragHandle = FindResizeableSlotBeforeHandle( DraggedHandle, Children );

	TArray< int32 > SlotsAfterDragHandleIndicies;
	if ( ResizeMode == ESplitterResizeMode::Fixed )
	{
		const int32 SlotAfterDragHandle = FindResizeableSlotAfterHandle( DraggedHandle, Children );

		if ( SlotAfterDragHandle < NumChildren )
		{
			SlotsAfterDragHandleIndicies.Add( SlotAfterDragHandle );
		}
	}
	else if ( ResizeMode == ESplitterResizeMode::Fill )
	{
		FindAllResizeableSlotsAfterHandle( DraggedHandle, Children, /*OUT*/ SlotsAfterDragHandleIndicies );
	}

	if ( SlotBeforeDragHandle >= 0 && SlotsAfterDragHandleIndicies.Num() > 0 )
	{
		struct FSlotInfo 
		{
			FSlot* Slot;
			const FLayoutGeometry* Geometry;
			float NewSize;
		};

		TArray< FSlotInfo > SlotsAfterDragHandle;
		for (int SlotIndex = 0; SlotIndex < SlotsAfterDragHandleIndicies.Num(); SlotIndex++)
		{
			FSlotInfo SlotInfo;

			SlotInfo.Slot = &Children[ SlotsAfterDragHandleIndicies[ SlotIndex ] ];
			SlotInfo.Geometry = &ChildGeometries[ SlotsAfterDragHandleIndicies[ SlotIndex ] ];
			SlotInfo.NewSize = SlotInfo.Geometry->GetSizeInParentSpace().Component( AxisIndex );

			SlotsAfterDragHandle.Add( SlotInfo );
		}

		// Get references the prev and next children and their layout settings so that we can modify them.
		FSlot& PrevChild = Children[SlotBeforeDragHandle];
		const FLayoutGeometry& PrevChildGeom = ChildGeometries[SlotBeforeDragHandle];

		// Compute the new sizes of the children
		const float PrevChildLength = PrevChildGeom.GetSizeInParentSpace().Component(AxisIndex);
		float NewPrevChildLength = ClampChild( PrevChildLength + Delta );
		Delta = NewPrevChildLength - PrevChildLength;

		// Distribute the Delta across the affected slots after the drag handle
		float UnusedDelta = Delta;
		for (int DistributionCount = 0; DistributionCount < SlotsAfterDragHandle.Num() && UnusedDelta != 0; DistributionCount++)
		{
			float DividedDelta = UnusedDelta / SlotsAfterDragHandle.Num();
			UnusedDelta = 0;
			for (int SlotIndex = 0; SlotIndex < SlotsAfterDragHandle.Num(); SlotIndex++)
			{
				FSlotInfo& SlotInfo = SlotsAfterDragHandle[ SlotIndex ];

				float CurrentSize = ClampChild( SlotInfo.Geometry->GetSizeInParentSpace().Component(AxisIndex) );
				SlotInfo.NewSize = ClampChild( CurrentSize - DividedDelta );

				// If one of the slots couldn't be fully adjusted by the delta due to min/max constraints then
				// the leftover delta needs to be evenly distributed to all of the other slots
				UnusedDelta += SlotInfo.NewSize - ( CurrentSize - DividedDelta );
			}
		}

		Delta = Delta - UnusedDelta;

		// PrevChildLength needs to be updated: it's value has to take into account the next child's min/max restrictions
		NewPrevChildLength = ClampChild( PrevChildLength + Delta );

		// Cells being resized are both stretch values -> redistribute the stretch coefficients proportionately
		// to match the new child sizes on the screen.
		{
			float TotalLength = NewPrevChildLength;
			float TotalStretchCoefficients = PrevChild.SizeValue.Get();

			for (int SlotIndex = 0; SlotIndex < SlotsAfterDragHandle.Num(); SlotIndex++)
			{
				FSlotInfo SlotInfo = SlotsAfterDragHandle[ SlotIndex ];

				TotalLength += SlotInfo.NewSize;
				TotalStretchCoefficients += SlotInfo.Slot->SizeValue.Get();
			}

			const float NewPrevChildSize = ( TotalStretchCoefficients * NewPrevChildLength / TotalLength );

			if (PrevChild.OnSlotResized_Handler.IsBound())
			{
				PrevChild.OnSlotResized_Handler.Execute( NewPrevChildSize );
			}
			else
			{
				PrevChild.SizeValue = NewPrevChildSize;
			}

			for (int SlotIndex = 0; SlotIndex < SlotsAfterDragHandle.Num(); SlotIndex++)
			{
				FSlotInfo SlotInfo = SlotsAfterDragHandle[ SlotIndex ];

				const float NewNextChildSize = ( TotalStretchCoefficients * SlotInfo.NewSize / TotalLength );

				if (SlotInfo.Slot->OnSlotResized_Handler.IsBound())
				{
					SlotInfo.Slot->OnSlotResized_Handler.Execute(NewNextChildSize);
				}
				else
				{
					SlotInfo.Slot->SizeValue = NewNextChildSize;
				}
			}
		}
	}
}