Files
UnrealEngineUWP/Engine/Source/Runtime/UMG/Private/Components/ScrollBox.cpp
patrick boutot e7fc3f9e55 UMG: Update UWidget::Visibility initialization from SetVisibility to SetVisibilityInternal.
[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]
2022-05-11 15:55:37 -04:00

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