You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Also fixes issue where any 32x32 button texture would get shrunk to zero on editor utility widgets. #preflight 620441552f56bd0ebf9fc84e #rb vincent.gauthier lauren.barnes #lockdown JeanMichel.Dignard #ROBOMERGE-AUTHOR: daren.cheng #ROBOMERGE-SOURCE: CL 18926528 via CL 18926776 via CL 18928248 via CL 18929495 #ROBOMERGE-BOT: UE5 (Release-Engine-Test -> Main) (v916-18915374) [CL 18929501 by daren cheng in ue5-main branch]
370 lines
8.7 KiB
C++
370 lines
8.7 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Components/ListView.h"
|
|
#include "Widgets/Views/SListView.h"
|
|
#include "Engine/World.h"
|
|
#include "TimerManager.h"
|
|
#include "Blueprint/ListViewDesignerPreviewItem.h"
|
|
#include "Styling/UMGCoreStyle.h"
|
|
#include "UMGPrivate.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "UMG"
|
|
|
|
/////////////////////////////////////////////////////
|
|
// UListView
|
|
|
|
static FTableViewStyle* DefaultListViewStyle = nullptr;
|
|
static FScrollBarStyle* DefaultListViewScrollBarStyle = nullptr;
|
|
|
|
#if WITH_EDITOR
|
|
static FTableViewStyle* EditorListViewStyle = nullptr;
|
|
static FScrollBarStyle* EditorListViewScrollBarStyle = nullptr;
|
|
#endif
|
|
|
|
UListView::UListView(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
, Orientation(EOrientation::Orient_Vertical)
|
|
{
|
|
if (DefaultListViewStyle == nullptr)
|
|
{
|
|
DefaultListViewStyle = new FTableViewStyle(FUMGCoreStyle::Get().GetWidgetStyle<FTableViewStyle>("ListView"));
|
|
|
|
// Unlink UMG default colors.
|
|
DefaultListViewStyle->UnlinkColors();
|
|
}
|
|
|
|
if (DefaultListViewScrollBarStyle == nullptr)
|
|
{
|
|
DefaultListViewScrollBarStyle = new FScrollBarStyle(FUMGCoreStyle::Get().GetWidgetStyle<FScrollBarStyle>("Scrollbar"));
|
|
|
|
// Unlink UMG default colors.
|
|
DefaultListViewScrollBarStyle->UnlinkColors();
|
|
}
|
|
|
|
WidgetStyle = *DefaultListViewStyle;
|
|
ScrollBarStyle = *DefaultListViewScrollBarStyle;
|
|
|
|
#if WITH_EDITOR
|
|
if (EditorListViewStyle == nullptr)
|
|
{
|
|
EditorListViewStyle = new FTableViewStyle(FAppStyle::Get().GetWidgetStyle<FTableViewStyle>("ListView"));
|
|
|
|
// Unlink UMG default colors.
|
|
EditorListViewStyle->UnlinkColors();
|
|
}
|
|
|
|
if (EditorListViewScrollBarStyle == nullptr)
|
|
{
|
|
EditorListViewScrollBarStyle = new FScrollBarStyle(FCoreStyle::Get().GetWidgetStyle<FScrollBarStyle>("Scrollbar"));
|
|
|
|
// Unlink UMG default colors.
|
|
EditorListViewScrollBarStyle->UnlinkColors();
|
|
}
|
|
|
|
if (IsEditorWidget())
|
|
{
|
|
WidgetStyle = *EditorListViewStyle;
|
|
ScrollBarStyle = *EditorListViewScrollBarStyle;
|
|
}
|
|
#endif // WITH_EDITOR
|
|
}
|
|
|
|
void UListView::ReleaseSlateResources(bool bReleaseChildren)
|
|
{
|
|
Super::ReleaseSlateResources(bReleaseChildren);
|
|
|
|
MyListView.Reset();
|
|
}
|
|
|
|
#if WITH_EDITOR
|
|
void UListView::OnRefreshDesignerItems()
|
|
{
|
|
RefreshDesignerItems<UObject*>(ListItems, [this] () {return NewObject<UListViewDesignerPreviewItem>(this); });
|
|
}
|
|
#endif
|
|
|
|
void UListView::AddItem(UObject* Item)
|
|
{
|
|
if (Item == nullptr)
|
|
{
|
|
FFrame::KismetExecutionMessage(TEXT("Cannot add null item into ListView."), ELogVerbosity::Warning, "NullListViewItem");
|
|
return;
|
|
}
|
|
|
|
if (ListItems.Contains(Item))
|
|
{
|
|
FFrame::KismetExecutionMessage(TEXT("Cannot add duplicate item into ListView."), ELogVerbosity::Warning, "DuplicateListViewItem");
|
|
return;
|
|
}
|
|
|
|
ListItems.Add(Item);
|
|
|
|
const TArray<UObject*> Added = { Item };
|
|
const TArray<UObject*> Removed;
|
|
OnItemsChanged(Added, Removed);
|
|
|
|
RequestRefresh();
|
|
}
|
|
|
|
void UListView::RemoveItem(UObject* Item)
|
|
{
|
|
ListItems.Remove(Item);
|
|
|
|
const TArray<UObject*> Added;
|
|
const TArray<UObject*> Removed = { Item };
|
|
OnItemsChanged(Added, Removed);
|
|
|
|
RequestRefresh();
|
|
}
|
|
|
|
UObject* UListView::GetItemAt(int32 Index) const
|
|
{
|
|
return ListItems.IsValidIndex(Index) ? ListItems[Index] : nullptr;
|
|
}
|
|
|
|
int32 UListView::GetNumItems() const
|
|
{
|
|
return ListItems.Num();
|
|
}
|
|
|
|
int32 UListView::GetIndexForItem(const UObject* Item) const
|
|
{
|
|
return ListItems.IndexOfByKey(Item);
|
|
}
|
|
|
|
void UListView::ClearListItems()
|
|
{
|
|
const TArray<UObject*> Added;
|
|
const TArray<UObject*> Removed = MoveTemp(ListItems);
|
|
|
|
ListItems.Reset();
|
|
|
|
OnItemsChanged(Added, Removed);
|
|
|
|
RequestRefresh();
|
|
}
|
|
|
|
void UListView::SetSelectionMode(TEnumAsByte<ESelectionMode::Type> InSelectionMode)
|
|
{
|
|
SelectionMode = InSelectionMode;
|
|
if (MyListView)
|
|
{
|
|
MyListView->SetSelectionMode(InSelectionMode);
|
|
}
|
|
}
|
|
|
|
int32 UListView::BP_GetNumItemsSelected() const
|
|
{
|
|
return GetNumItemsSelected();
|
|
}
|
|
|
|
void UListView::BP_SetListItems(const TArray<UObject*>& InListItems)
|
|
{
|
|
SetListItems(InListItems);
|
|
}
|
|
|
|
UObject* UListView::BP_GetSelectedItem() const
|
|
{
|
|
return GetSelectedItem();
|
|
}
|
|
|
|
void UListView::HandleOnEntryInitializedInternal(UObject* Item, const TSharedRef<ITableRow>& TableRow)
|
|
{
|
|
BP_OnEntryInitialized.Broadcast(Item, GetEntryWidgetFromItem(Item));
|
|
}
|
|
|
|
bool UListView::BP_GetSelectedItems(TArray<UObject*>& Items) const
|
|
{
|
|
return GetSelectedItems(Items) > 0;
|
|
}
|
|
|
|
bool UListView::BP_IsItemVisible(UObject* Item) const
|
|
{
|
|
return IsItemVisible(Item);
|
|
}
|
|
|
|
void UListView::BP_NavigateToItem(UObject* Item)
|
|
{
|
|
if (Item)
|
|
{
|
|
RequestNavigateToItem(Item);
|
|
}
|
|
}
|
|
|
|
void UListView::NavigateToIndex(int32 Index)
|
|
{
|
|
RequestNavigateToItem(GetItemAt(Index));
|
|
}
|
|
|
|
void UListView::BP_ScrollItemIntoView(UObject* Item)
|
|
{
|
|
if (Item)
|
|
{
|
|
RequestScrollItemIntoView(Item);
|
|
}
|
|
}
|
|
|
|
void UListView::ScrollIndexIntoView(int32 Index)
|
|
{
|
|
BP_ScrollItemIntoView(GetItemAt(Index));
|
|
}
|
|
|
|
void UListView::BP_CancelScrollIntoView()
|
|
{
|
|
if (MyListView.IsValid())
|
|
{
|
|
MyListView->CancelScrollIntoView();
|
|
}
|
|
}
|
|
|
|
bool UListView::IsRefreshPending() const
|
|
{
|
|
if (MyListView.IsValid())
|
|
{
|
|
return MyListView->IsPendingRefresh();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void UListView::BP_SetSelectedItem(UObject* Item)
|
|
{
|
|
if (MyListView.IsValid())
|
|
{
|
|
MyListView->SetSelection(Item, ESelectInfo::Direct);
|
|
}
|
|
}
|
|
|
|
void UListView::SetSelectedItem(const UObject* Item)
|
|
{
|
|
ITypedUMGListView<UObject*>::SetSelectedItem(const_cast<UObject*>(Item));
|
|
}
|
|
|
|
void UListView::SetSelectedIndex(int32 Index)
|
|
{
|
|
SetSelectedItem(GetItemAt(Index));
|
|
}
|
|
|
|
void UListView::BP_SetItemSelection(UObject* Item, bool bSelected)
|
|
{
|
|
SetItemSelection(Item, bSelected);
|
|
}
|
|
|
|
void UListView::BP_ClearSelection()
|
|
{
|
|
ClearSelection();
|
|
}
|
|
|
|
void UListView::OnItemsChanged(const TArray<UObject*>& AddedItems, const TArray<UObject*>& RemovedItems)
|
|
{
|
|
// Allow subclasses to do special things when objects are added or removed from the list.
|
|
|
|
// Keep track of references to Actors and make sure to release them when Actors are about to be removed
|
|
for (UObject* AddedItem : AddedItems)
|
|
{
|
|
if (AActor* AddedActor = Cast<AActor>(AddedItem))
|
|
{
|
|
AddedActor->OnEndPlay.AddDynamic(this, &UListView::OnListItemEndPlayed);
|
|
}
|
|
else if (AActor* AddedItemOuterActor = AddedItem->GetTypedOuter<AActor>())
|
|
{
|
|
// Unique so that we don't spam events for shared actor outers but this also means we can't
|
|
// unsubscribe when processing RemovedItems
|
|
AddedItemOuterActor->OnEndPlay.AddUniqueDynamic(this, &UListView::OnListItemOuterEndPlayed);
|
|
}
|
|
}
|
|
for (UObject* RemovedItem : RemovedItems)
|
|
{
|
|
if (AActor* RemovedActor = Cast<AActor>(RemovedItem))
|
|
{
|
|
RemovedActor->OnEndPlay.RemoveDynamic(this, &UListView::OnListItemEndPlayed);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UListView::OnListItemEndPlayed(AActor* Item, EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
RemoveItem(Item);
|
|
}
|
|
|
|
void UListView::OnListItemOuterEndPlayed(AActor* ItemOuter, EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
for (int32 ItemIndex = ListItems.Num() - 1; ItemIndex >= 0; --ItemIndex)
|
|
{
|
|
UObject* Item = ListItems[ItemIndex];
|
|
if (Item->IsIn(ItemOuter))
|
|
{
|
|
RemoveItem(Item);
|
|
}
|
|
}
|
|
}
|
|
|
|
TSharedRef<STableViewBase> UListView::RebuildListWidget()
|
|
{
|
|
return ConstructListView<SListView>();
|
|
}
|
|
|
|
void UListView::HandleListEntryHovered(UUserWidget& EntryWidget)
|
|
{
|
|
if (UObject* const* ListItem = ItemFromEntryWidget(EntryWidget))
|
|
{
|
|
OnItemIsHoveredChanged().Broadcast(*ListItem, true);
|
|
BP_OnItemIsHoveredChanged.Broadcast(*ListItem, true);
|
|
}
|
|
}
|
|
|
|
void UListView::HandleListEntryUnhovered(UUserWidget& EntryWidget)
|
|
{
|
|
if (UObject* const* ListItem = ItemFromEntryWidget(EntryWidget))
|
|
{
|
|
OnItemIsHoveredChanged().Broadcast(*ListItem, false);
|
|
BP_OnItemIsHoveredChanged.Broadcast(*ListItem, false);
|
|
}
|
|
}
|
|
|
|
FMargin UListView::GetDesiredEntryPadding(UObject* Item) const
|
|
{
|
|
if (ListItems.Num() > 0 && ListItems[0] != Item)
|
|
{
|
|
if (Orientation == EOrientation::Orient_Horizontal)
|
|
{
|
|
// For all entries after the first one, add the spacing as left padding
|
|
return FMargin(EntrySpacing, 0.f, 0.0f, 0.f);
|
|
}
|
|
else
|
|
{
|
|
// For all entries after the first one, add the spacing as top padding
|
|
return FMargin(0.f, EntrySpacing, 0.f, 0.f);
|
|
}
|
|
}
|
|
|
|
return FMargin(0.f);
|
|
}
|
|
|
|
UUserWidget& UListView::OnGenerateEntryWidgetInternal(UObject* Item, TSubclassOf<UUserWidget> DesiredEntryClass, const TSharedRef<STableViewBase>& OwnerTable)
|
|
{
|
|
return GenerateTypedEntry(DesiredEntryClass, OwnerTable);
|
|
}
|
|
|
|
void UListView::OnItemClickedInternal(UObject* ListItem)
|
|
{
|
|
BP_OnItemClicked.Broadcast(ListItem);
|
|
}
|
|
|
|
void UListView::OnItemDoubleClickedInternal(UObject* ListItem)
|
|
{
|
|
BP_OnItemDoubleClicked.Broadcast(ListItem);
|
|
}
|
|
|
|
void UListView::OnSelectionChangedInternal(UObject* FirstSelectedItem)
|
|
{
|
|
BP_OnItemSelectionChanged.Broadcast(FirstSelectedItem, FirstSelectedItem != nullptr);
|
|
}
|
|
|
|
void UListView::OnItemScrolledIntoViewInternal(UObject* ListItem, UUserWidget& EntryWidget)
|
|
{
|
|
BP_OnItemScrolledIntoView.Broadcast(ListItem, &EntryWidget);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
#undef LOCTEXT_NAMESPACE |