Files
UnrealEngine/Engine/Source/Editor/ContentBrowser/Private/Widgets/SContentBrowserSourceTree.h
2025-05-18 13:04:45 +08:00

209 lines
6.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Containers/Array.h"
#include "Containers/ArrayView.h"
#include "Containers/UnrealString.h"
#include "Framework/Layout/IScrollableWidget.h"
#include "Framework/SlateDelegates.h"
#include "HAL/Platform.h"
#include "Input/Reply.h"
#include "Internationalization/Text.h"
#include "Layout/Visibility.h"
#include "Misc/Optional.h"
#include "Templates/SharedPointer.h"
#include "Templates/UnrealTemplate.h"
#include "Types/SlateEnums.h"
#include "UObject/NameTypes.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/Docking/SDockTab.h"
#include "Widgets/Layout/SSplitter.h"
#include "Widgets/SCompoundWidget.h"
class FSourcesSearch;
class SSearchToggleButton;
namespace UE::Editor::ContentBrowser::Private
{
class SContentBrowserSourceTree;
class SContentBrowserSourceTreeArea;
/** The Content Browser Source Tree, containing "Favorites", etc. */
class SContentBrowserSourceTree : public SCompoundWidget
{
using Super = SCompoundWidget;
public:
class FSlot : public TSlotBase<FSlot>
{
public:
SLATE_SLOT_BEGIN_ARGS(FSlot, TSlotBase<FSlot>)
SLATE_ARGUMENT(TSharedPtr<SContentBrowserSourceTreeArea>, AreaWidget)
SLATE_ARGUMENT(TOptional<float>, Size)
SLATE_ARGUMENT(TOptional<SSplitter::ESizeRule>, ExpandedSizeRule)
SLATE_ATTRIBUTE(EVisibility, Visibility)
SLATE_ARGUMENT(TOptional<float>, HeaderHeight)
SLATE_SLOT_END_ARGS()
void Construct(const FChildren& SlotOwner, FSlotArguments&& InArgs);
public:
SSplitter::ESizeRule GetExpandedSizeRule() const;
SSplitter::ESizeRule GetEmptyExpandedSizeRule() const;
float GetMinHeight() const;
float GetHeaderHeight() const;
float GetInitialSlotSize() const;
float GetSlotSize() const;
TSharedPtr<SContentBrowserSourceTreeArea> GetEntryWidget() const;
bool IsVisible() const;
void OnSlotResized(float InNewSize);
private:
SSplitter::ESizeRule ExpandedSizeRule = SSplitter::ESizeRule::FractionOfParent;
SSplitter::ESizeRule EmptyExpandedSizeRule = SSplitter::ESizeRule::FractionOfParent;
float HeaderHeight = 36.0f;
float InitialSlotSize = 0.0f;
float SlotSize = 0.0f; // The current slot height
TSharedPtr<SContentBrowserSourceTreeArea> EntryWidget = nullptr;
TAttribute<EVisibility> EntryVisibility;
};
public:
/** @return Add a new FSlot(). */
static FSlot::FSlotArguments Slot();
SLATE_BEGIN_ARGS(SContentBrowserSourceTree)
{ }
SLATE_SLOT_ARGUMENT(FSlot, Slots)
SLATE_END_ARGS()
SContentBrowserSourceTree()
: Slots(this)
, TotalHeaderHeight(0.0f)
{
}
/**
* Constructs this widget with InArgs.
*/
void Construct(const FArguments& InArgs);
TSharedPtr<SSplitter> GetSplitter() const { return Splitter; }
using FScopedWidgetSlotArguments = TPanelChildren<FSlot>::FScopedWidgetSlotArguments;
FScopedWidgetSlotArguments AddSlot(const int32 InAtIndex = INDEX_NONE);
/** Removes a slot from this panel which contains the specified SWidget
*
* @param InSlotWidget The widget to match when searching through the slots
* @returns The index in the children array where the slot was removed and -1 if no slot was found matching the widget
*/
int32 RemoveSlot(const TSharedRef<SWidget>& InSlotWidget);
/** Removes all children from the panel. */
void ClearChildren();
/** @return the number of slots. */
int32 NumSlots() const;
/** @return if it's a valid index slot index. */
bool IsValidSlotIndex(int32 InIndex) const;
private:
float GetMinHeight(TSharedPtr<SContentBrowserSourceTreeArea> InEntryWidget) const;
float GetTotalHeaderHeight() const;
SSplitter::ESizeRule GetExpandedSizeRule(TSharedPtr<SContentBrowserSourceTreeArea> InEntryWidget) const;
float GetSlotSize(const int32 InSlotIdx) const;
void OnSlotResized(float InNewSize, const int32 InSlotIdx);
void UpdateTotalHeaderHeight();
private:
TSharedPtr<SSplitter> Splitter;
TPanelChildren<FSlot> Slots;
/** Cached total header height, recalculated one Slot Add/Remove. */
float TotalHeaderHeight;
};
/** Represents a single item in the source tree view, ie. "Favorites". */
class SContentBrowserSourceTreeArea : public SCompoundWidget
{
using Super = SCompoundWidget;
public:
SLATE_BEGIN_ARGS(SContentBrowserSourceTreeArea)
: _IsEmpty(false)
{ }
/** Label to display in the header, ie. "Favorites" */
SLATE_ATTRIBUTE(FText, Label)
/** (Optional) content displayed to the right of the header label. */
SLATE_NAMED_SLOT(FArguments, HeaderContent)
/** (Optional) bind to notify when this widget should switch to an empty state. */
SLATE_ATTRIBUTE(bool, IsEmpty)
/** (Optional) label to display in the body area when the body is empty, shown as RichText. */
SLATE_ATTRIBUTE(FText, EmptyBodyLabel)
/** (Optional) default state for area expansion. */
SLATE_ARGUMENT(bool, ExpandedByDefault)
/** Called when the area is expanded or collapsed */
SLATE_EVENT(FOnBooleanValueChanged, OnExpansionChanged)
SLATE_END_ARGS()
/**
* Constructs this widget with InArgs.
* @param Id Used to identify the role of this widget (Favorites, etc.) for config settings, etc.
* @param InSearch (Optional) Search for this area and it's contained items.
* @param InBody The Body widget, which must implement IScrollableWidget
*/
void Construct(const FArguments& InArgs, const FName InId, const TSharedPtr<FSourcesSearch>& InSearch, TSharedRef<IScrollableWidget> InBody);
bool IsExpanded() const;
void SetExpanded(bool bInExpanded);
/** Returns true if the contents is "Empty", regardless of expansion state. */
bool IsEmpty() const;
/** Saves all persistent settings to config. */
void SaveSettings(const FString& InIniFilename, const FString& InIniSection, const FString& InSettingsString) const;
/** Loads settings from config based on the browser's InstanceName. */
void LoadSettings(const FString& InIniFilename, const FString& InIniSection, const FString& InSettingsString);
bool HasSearch() const { return Search.IsValid(); }
TSharedPtr<SSearchToggleButton> GetSearchToggleButton() const;
private:
EVisibility GetHeaderSearchActionVisibility() const;
void OnAreaExpansionChanged(bool bInIsExpanded);
private:
FName Id;
TAttribute<bool> bIsEmpty;
/** The (optional) source search. */
TSharedPtr<FSourcesSearch> Search = nullptr;
/** Toggle button for showing/hiding the search area, only visible if Search IsValid. */
TSharedPtr<SSearchToggleButton> SearchToggleButton = nullptr;
TSharedPtr<IScrollableWidget> BodyScrollableWidget;
TSharedPtr<SExpandableArea> ExpandableArea;
FOnBooleanValueChanged OnExpansionChanged;
bool bExpandedByDefault = false;
};
}