You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
[FYI] vincent.gauthier #ROBOMERGE-AUTHOR: patrick.boutot #ROBOMERGE-SOURCE: CL 20142060 via CL 20143142 via CL 20143633 #ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v943-19904690) [CL 20148091 by patrick boutot in ue5-main branch]
439 lines
12 KiB
C++
439 lines
12 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Components/ScrollBox.h"
|
|
#include "Containers/Ticker.h"
|
|
#include "Components/ScrollBoxSlot.h"
|
|
#include "UObject/EditorObjectVersion.h"
|
|
#include "Styling/UMGCoreStyle.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "UMG"
|
|
|
|
/////////////////////////////////////////////////////
|
|
// UScrollBox
|
|
|
|
static FScrollBoxStyle* DefaultScrollBoxStyle = nullptr;
|
|
static FScrollBarStyle* DefaultScrollBoxBarStyle = nullptr;
|
|
|
|
#if WITH_EDITOR
|
|
static FScrollBoxStyle* EditorScrollBoxStyle = nullptr;
|
|
static FScrollBarStyle* EditorScrollBoxBarStyle = nullptr;
|
|
#endif
|
|
|
|
UScrollBox::UScrollBox(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
, Orientation(Orient_Vertical)
|
|
, ScrollBarVisibility(ESlateVisibility::Visible)
|
|
, ConsumeMouseWheel(EConsumeMouseWheel::WhenScrollingPossible)
|
|
, ScrollbarThickness(9.0f, 9.0f)
|
|
, ScrollbarPadding(2.0f)
|
|
, AlwaysShowScrollbar(false)
|
|
, AlwaysShowScrollbarTrack(false)
|
|
, AllowOverscroll(true)
|
|
, BackPadScrolling(false)
|
|
, FrontPadScrolling(false)
|
|
, NavigationDestination(EDescendantScrollDestination::IntoView)
|
|
, NavigationScrollPadding(0.0f)
|
|
, ScrollWhenFocusChanges(EScrollWhenFocusChanges::NoScroll)
|
|
{
|
|
bIsVariable = false;
|
|
|
|
SetVisibilityInternal(ESlateVisibility::Visible);
|
|
SetClipping(EWidgetClipping::ClipToBounds);
|
|
|
|
if (DefaultScrollBoxStyle == nullptr)
|
|
{
|
|
DefaultScrollBoxStyle = new FScrollBoxStyle(FUMGCoreStyle::Get().GetWidgetStyle<FScrollBoxStyle>("ScrollBox"));
|
|
|
|
// Unlink UMG default colors.
|
|
DefaultScrollBoxStyle->UnlinkColors();
|
|
}
|
|
|
|
if (DefaultScrollBoxBarStyle == nullptr)
|
|
{
|
|
DefaultScrollBoxBarStyle = new FScrollBarStyle(FUMGCoreStyle::Get().GetWidgetStyle<FScrollBarStyle>("ScrollBar"));
|
|
|
|
// Unlink UMG default colors.
|
|
DefaultScrollBoxBarStyle->UnlinkColors();
|
|
}
|
|
|
|
WidgetStyle = *DefaultScrollBoxStyle;
|
|
WidgetBarStyle = *DefaultScrollBoxBarStyle;
|
|
|
|
#if WITH_EDITOR
|
|
if (EditorScrollBoxStyle == nullptr)
|
|
{
|
|
EditorScrollBoxStyle = new FScrollBoxStyle(FCoreStyle::Get().GetWidgetStyle<FScrollBoxStyle>("ScrollBox"));
|
|
|
|
// Unlink UMG Editor colors from the editor settings colors.
|
|
EditorScrollBoxStyle->UnlinkColors();
|
|
}
|
|
|
|
if (EditorScrollBoxBarStyle == nullptr)
|
|
{
|
|
EditorScrollBoxBarStyle = new FScrollBarStyle(FCoreStyle::Get().GetWidgetStyle<FScrollBarStyle>("ScrollBar"));
|
|
|
|
// Unlink UMG Editor colors from the editor settings colors.
|
|
EditorScrollBoxBarStyle->UnlinkColors();
|
|
}
|
|
|
|
if (IsEditorWidget())
|
|
{
|
|
WidgetStyle = *EditorScrollBoxStyle;
|
|
WidgetBarStyle = *EditorScrollBoxBarStyle;
|
|
|
|
// The CDO isn't an editor widget and thus won't use the editor style, call post edit change to mark difference from CDO
|
|
PostEditChange();
|
|
}
|
|
#endif // WITH_EDITOR
|
|
|
|
bAllowRightClickDragScrolling = true;
|
|
}
|
|
|
|
void UScrollBox::ReleaseSlateResources(bool bReleaseChildren)
|
|
{
|
|
Super::ReleaseSlateResources(bReleaseChildren);
|
|
|
|
MyScrollBox.Reset();
|
|
}
|
|
|
|
UClass* UScrollBox::GetSlotClass() const
|
|
{
|
|
return UScrollBoxSlot::StaticClass();
|
|
}
|
|
|
|
void UScrollBox::OnSlotAdded(UPanelSlot* InSlot)
|
|
{
|
|
// Add the child to the live canvas if it already exists
|
|
if ( MyScrollBox.IsValid() )
|
|
{
|
|
CastChecked<UScrollBoxSlot>(InSlot)->BuildSlot(MyScrollBox.ToSharedRef());
|
|
}
|
|
}
|
|
|
|
void UScrollBox::OnSlotRemoved(UPanelSlot* InSlot)
|
|
{
|
|
// Remove the widget from the live slot if it exists.
|
|
if ( MyScrollBox.IsValid() && InSlot->Content)
|
|
{
|
|
TSharedPtr<SWidget> Widget = InSlot->Content->GetCachedWidget();
|
|
if ( Widget.IsValid() )
|
|
{
|
|
MyScrollBox->RemoveSlot(Widget.ToSharedRef());
|
|
}
|
|
}
|
|
}
|
|
|
|
TSharedRef<SWidget> UScrollBox::RebuildWidget()
|
|
{
|
|
MyScrollBox = SNew(SScrollBox)
|
|
.Style(&WidgetStyle)
|
|
.ScrollBarStyle(&WidgetBarStyle)
|
|
.Orientation(Orientation)
|
|
.ConsumeMouseWheel(ConsumeMouseWheel)
|
|
.NavigationDestination(NavigationDestination)
|
|
.NavigationScrollPadding(NavigationScrollPadding)
|
|
.ScrollWhenFocusChanges(ScrollWhenFocusChanges)
|
|
.BackPadScrolling(BackPadScrolling)
|
|
.FrontPadScrolling(FrontPadScrolling)
|
|
.AnimateWheelScrolling(bAnimateWheelScrolling)
|
|
.WheelScrollMultiplier(WheelScrollMultiplier)
|
|
.OnUserScrolled(BIND_UOBJECT_DELEGATE(FOnUserScrolled, SlateHandleUserScrolled));
|
|
|
|
for ( UPanelSlot* PanelSlot : Slots )
|
|
{
|
|
if ( UScrollBoxSlot* TypedSlot = Cast<UScrollBoxSlot>(PanelSlot) )
|
|
{
|
|
TypedSlot->Parent = this;
|
|
TypedSlot->BuildSlot(MyScrollBox.ToSharedRef());
|
|
}
|
|
}
|
|
|
|
return MyScrollBox.ToSharedRef();
|
|
}
|
|
|
|
void UScrollBox::SynchronizeProperties()
|
|
{
|
|
Super::SynchronizeProperties();
|
|
|
|
MyScrollBox->SetScrollOffset(DesiredScrollOffset);
|
|
MyScrollBox->SetOrientation(Orientation);
|
|
MyScrollBox->SetScrollBarVisibility(UWidget::ConvertSerializedVisibilityToRuntime(ScrollBarVisibility));
|
|
MyScrollBox->SetScrollBarThickness(ScrollbarThickness);
|
|
MyScrollBox->SetScrollBarPadding(ScrollbarPadding);
|
|
MyScrollBox->SetScrollBarAlwaysVisible(AlwaysShowScrollbar);
|
|
MyScrollBox->SetScrollBarTrackAlwaysVisible(AlwaysShowScrollbarTrack);
|
|
MyScrollBox->SetAllowOverscroll(AllowOverscroll ? EAllowOverscroll::Yes : EAllowOverscroll::No);
|
|
MyScrollBox->SetScrollBarRightClickDragAllowed(bAllowRightClickDragScrolling);
|
|
MyScrollBox->SetConsumeMouseWheel(ConsumeMouseWheel);
|
|
MyScrollBox->SetAnimateWheelScrolling(bAnimateWheelScrolling);
|
|
MyScrollBox->SetWheelScrollMultiplier(WheelScrollMultiplier);
|
|
}
|
|
|
|
float UScrollBox::GetScrollOffset() const
|
|
{
|
|
if ( MyScrollBox.IsValid() )
|
|
{
|
|
return MyScrollBox->GetScrollOffset();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
float UScrollBox::GetScrollOffsetOfEnd() const
|
|
{
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
return MyScrollBox->GetScrollOffsetOfEnd();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
float UScrollBox::GetViewOffsetFraction() const
|
|
{
|
|
if ( MyScrollBox.IsValid() )
|
|
{
|
|
return MyScrollBox->GetViewOffsetFraction();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void UScrollBox::SetScrollOffset(float NewScrollOffset)
|
|
{
|
|
DesiredScrollOffset = NewScrollOffset;
|
|
|
|
if ( MyScrollBox.IsValid() )
|
|
{
|
|
MyScrollBox->SetScrollOffset(NewScrollOffset);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::ScrollToStart()
|
|
{
|
|
if ( MyScrollBox.IsValid() )
|
|
{
|
|
MyScrollBox->ScrollToStart();
|
|
}
|
|
}
|
|
|
|
void UScrollBox::ScrollToEnd()
|
|
{
|
|
if ( MyScrollBox.IsValid() )
|
|
{
|
|
MyScrollBox->ScrollToEnd();
|
|
}
|
|
}
|
|
|
|
void UScrollBox::ScrollWidgetIntoView(UWidget* WidgetToFind, bool AnimateScroll, EDescendantScrollDestination InScrollDestination, float Padding)
|
|
{
|
|
TSharedPtr<SWidget> SlateWidgetToFind;
|
|
if (WidgetToFind)
|
|
{
|
|
SlateWidgetToFind = WidgetToFind->GetCachedWidget();
|
|
}
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
// NOTE: Pass even if null! This, in effect, cancels a request to scroll which is necessary to avoid warnings/ensures
|
|
// when we request to scroll to a widget and later remove that widget!
|
|
MyScrollBox->ScrollDescendantIntoView(SlateWidgetToFind, AnimateScroll, InScrollDestination, Padding);
|
|
}
|
|
}
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
|
|
void UScrollBox::Serialize(FArchive& Ar)
|
|
{
|
|
Ar.UsingCustomVersion(FEditorObjectVersion::GUID);
|
|
|
|
const bool bDeprecateThickness = Ar.IsLoading() && Ar.CustomVer(FEditorObjectVersion::GUID) < FEditorObjectVersion::ScrollBarThicknessChange;
|
|
if (bDeprecateThickness)
|
|
{
|
|
// Set ScrollbarThickness property to previous default value.
|
|
ScrollbarThickness.Set(5.0f, 5.0f);
|
|
}
|
|
|
|
Super::Serialize(Ar);
|
|
|
|
if (bDeprecateThickness)
|
|
{
|
|
// Implicit padding of 2 was removed, so ScrollbarThickness value must be incremented by 4.
|
|
ScrollbarThickness += FVector2D(4.0f, 4.0f);
|
|
}
|
|
}
|
|
|
|
#endif // if WITH_EDITORONLY_DATA
|
|
|
|
void UScrollBox::SetNavigationDestination(const EDescendantScrollDestination NewNavigationDestination)
|
|
{
|
|
NavigationDestination = NewNavigationDestination;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->SetNavigationDestination(NewNavigationDestination);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetConsumeMouseWheel(EConsumeMouseWheel NewConsumeMouseWheel)
|
|
{
|
|
ConsumeMouseWheel = NewConsumeMouseWheel;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->SetConsumeMouseWheel(NewConsumeMouseWheel);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetOrientation(EOrientation NewOrientation)
|
|
{
|
|
Orientation = NewOrientation;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->SetOrientation(Orientation);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetScrollBarVisibility(ESlateVisibility NewScrollBarVisibility)
|
|
{
|
|
ScrollBarVisibility = NewScrollBarVisibility;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
switch (ScrollBarVisibility)
|
|
{
|
|
case ESlateVisibility::Collapsed: MyScrollBox->SetScrollBarVisibility(EVisibility::Collapsed); break;
|
|
case ESlateVisibility::Hidden: MyScrollBox->SetScrollBarVisibility(EVisibility::Hidden); break;
|
|
case ESlateVisibility::HitTestInvisible: MyScrollBox->SetScrollBarVisibility(EVisibility::HitTestInvisible); break;
|
|
case ESlateVisibility::SelfHitTestInvisible: MyScrollBox->SetScrollBarVisibility(EVisibility::SelfHitTestInvisible); break;
|
|
case ESlateVisibility::Visible: MyScrollBox->SetScrollBarVisibility(EVisibility::Visible); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetScrollbarThickness(const FVector2D& NewScrollbarThickness)
|
|
{
|
|
ScrollbarThickness = NewScrollbarThickness;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->SetScrollBarThickness(ScrollbarThickness);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetScrollbarPadding(const FMargin& NewScrollbarPadding)
|
|
{
|
|
ScrollbarPadding = NewScrollbarPadding;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->SetScrollBarPadding(ScrollbarPadding);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetAlwaysShowScrollbar(bool NewAlwaysShowScrollbar)
|
|
{
|
|
AlwaysShowScrollbar = NewAlwaysShowScrollbar;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->SetScrollBarAlwaysVisible(AlwaysShowScrollbar);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetAllowOverscroll(bool NewAllowOverscroll)
|
|
{
|
|
AllowOverscroll = NewAllowOverscroll;
|
|
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->SetAllowOverscroll(AllowOverscroll ? EAllowOverscroll::Yes : EAllowOverscroll::No);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetAnimateWheelScrolling(bool bShouldAnimateWheelScrolling)
|
|
{
|
|
bAnimateWheelScrolling = bShouldAnimateWheelScrolling;
|
|
if (MyScrollBox)
|
|
{
|
|
MyScrollBox->SetAnimateWheelScrolling(bShouldAnimateWheelScrolling);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetWheelScrollMultiplier(float NewWheelScrollMultiplier)
|
|
{
|
|
WheelScrollMultiplier = NewWheelScrollMultiplier;
|
|
if (MyScrollBox)
|
|
{
|
|
MyScrollBox->SetWheelScrollMultiplier(NewWheelScrollMultiplier);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SetScrollWhenFocusChanges(EScrollWhenFocusChanges NewScrollWhenFocusChanges)
|
|
{
|
|
ScrollWhenFocusChanges = NewScrollWhenFocusChanges;
|
|
if (MyScrollBox)
|
|
{
|
|
MyScrollBox->SetScrollWhenFocusChanges(NewScrollWhenFocusChanges);
|
|
}
|
|
}
|
|
|
|
void UScrollBox::EndInertialScrolling()
|
|
{
|
|
if (MyScrollBox.IsValid())
|
|
{
|
|
MyScrollBox->EndInertialScrolling();
|
|
}
|
|
}
|
|
|
|
void UScrollBox::SlateHandleUserScrolled(float CurrentOffset)
|
|
{
|
|
OnUserScrolled.Broadcast(CurrentOffset);
|
|
}
|
|
|
|
#if WITH_EDITOR
|
|
|
|
const FText UScrollBox::GetPaletteCategory()
|
|
{
|
|
return LOCTEXT("Panel", "Panel");
|
|
}
|
|
|
|
void UScrollBox::OnDescendantSelectedByDesigner( UWidget* DescendantWidget )
|
|
{
|
|
UWidget* SelectedChild = UWidget::FindChildContainingDescendant( this, DescendantWidget );
|
|
if ( SelectedChild )
|
|
{
|
|
ScrollWidgetIntoView( SelectedChild, true );
|
|
|
|
if ( TickHandle.IsValid() )
|
|
{
|
|
FTSTicker::GetCoreTicker().RemoveTicker( TickHandle );
|
|
TickHandle.Reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
void UScrollBox::OnDescendantDeselectedByDesigner( UWidget* DescendantWidget )
|
|
{
|
|
if ( TickHandle.IsValid() )
|
|
{
|
|
FTSTicker::GetCoreTicker().RemoveTicker( TickHandle );
|
|
TickHandle.Reset();
|
|
}
|
|
|
|
// because we get a deselect before we get a select, we need to delay this call until we're sure we didn't scroll to another widget.
|
|
TickHandle = FTSTicker::GetCoreTicker().AddTicker( FTickerDelegate::CreateLambda( [=]( float ) -> bool
|
|
{
|
|
QUICK_SCOPE_CYCLE_COUNTER(STAT_UScrollBox_ScrollToStart_LambdaTick);
|
|
this->ScrollToStart();
|
|
return false;
|
|
} ) );
|
|
}
|
|
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
#undef LOCTEXT_NAMESPACE
|