Files
UnrealEngine/Engine/Source/Editor/UnrealEd/Private/PropertyInfoViewStyle.cpp
2025-05-18 13:04:45 +08:00

290 lines
7.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PropertyInfoViewStyle.h"
#include "Framework/Application/SlateApplication.h"
#include "GenericPlatform/GenericApplication.h"
#include "Internationalization/Text.h"
#include "Layout/Children.h"
#include "Layout/Geometry.h"
#include "Layout/Margin.h"
#include "Math/Color.h"
#include "Math/Vector2D.h"
#include "Misc/AssertionMacros.h"
#include "Rendering/DrawElements.h"
#include "Rendering/RenderingCommon.h"
#include "SlotBase.h"
#include "Styling/AppStyle.h"
#include "Styling/CoreStyle.h"
#include "Styling/ISlateStyle.h"
#include "Styling/SlateBrush.h"
#include "Types/SlateEnums.h"
#include "UObject/NameTypes.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Layout/SBox.h"
#include "Widgets/SOverlay.h"
#include "Widgets/SWidget.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Views/ITableRow.h"
class FPaintArgs;
class FSlateRect;
class FWidgetStyle;
namespace PropertyInfoViewStyle
{
FSlateColor GetIndentBackgroundColor(int32 IndentLevel, bool IsHovered)
{
if (IsHovered)
{
return FAppStyle::Get().GetSlateColor("Colors.Header");
}
if (IndentLevel == 0)
{
return FAppStyle::Get().GetSlateColor("Colors.Panel");
}
int32 ColorIndex = 0;
int32 Increment = 1;
for (int IndentCount = 0; IndentCount < IndentLevel; ++IndentCount)
{
ColorIndex += Increment;
if (ColorIndex == 0 || ColorIndex == 3)
{
Increment = -Increment;
}
}
static const uint8 ColorOffsets[] =
{
2, 6, 12, 20
};
FColor BaseColor = FAppStyle::Get().GetSlateColor("Colors.Panel").GetSpecifiedColor().ToFColor(true);
FColor ColorWithOffset(
BaseColor.R + ColorOffsets[ColorIndex],
BaseColor.G + ColorOffsets[ColorIndex],
BaseColor.B + ColorOffsets[ColorIndex]);
return FSlateColor(FLinearColor::FromSRGBColor(ColorWithOffset));
}
FSlateColor GetRowBackgroundColor(ITableRow* Row)
{
check(Row);
return GetIndentBackgroundColor(Row->GetIndentLevel(), Row->AsWidget()->IsHovered());
}
int32 SIndent::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements,
int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
TSharedPtr<ITableRow> RowPtr = Row.Pin();
if (!RowPtr.IsValid())
{
return LayerId;
}
const FSlateBrush* BackgroundBrush = FAppStyle::Get().GetBrush("DetailsView.CategoryMiddle");
const FSlateBrush* DropShadowBrush = FAppStyle::Get().GetBrush("DetailsView.ArrayDropShadow");
int32 IndentLevel = RowPtr->GetIndentLevel();
for (int32 IndentCount = 0; IndentCount < IndentLevel; ++IndentCount)
{
FSlateColor BackgroundColor = GetRowBackgroundColor(IndentCount);
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(TabSize, AllottedGeometry.GetLocalSize().Y), FSlateLayoutTransform(FVector2f(TabSize * IndentCount, 0.f))),
BackgroundBrush,
ESlateDrawEffect::None,
BackgroundColor.GetColor(InWidgetStyle)
);
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId + 1,
AllottedGeometry.ToPaintGeometry(FVector2f(TabSize, AllottedGeometry.GetLocalSize().Y), FSlateLayoutTransform(FVector2f(TabSize * IndentCount, 0.f))),
DropShadowBrush
);
}
return LayerId + 1;
}
void SIndent::Construct(const FArguments& InArgs, TSharedRef<ITableRow> DetailsRow)
{
Row = DetailsRow;
ChildSlot
[
SNew(SBox)
.WidthOverride(this, &SIndent::GetIndentWidth)
];
}
FOptionalSize SIndent::GetIndentWidth() const
{
int32 IndentLevel = 0;
TSharedPtr<ITableRow> RowPtr = Row.Pin();
if (RowPtr.IsValid())
{
IndentLevel = RowPtr->GetIndentLevel();
}
return IndentLevel * TabSize;
}
FSlateColor SIndent::GetRowBackgroundColor(int32 IndentLevel) const
{
const bool IsHovered = Row.IsValid() && Row.Pin()->AsWidget()->IsHovered();
return PropertyInfoViewStyle::GetIndentBackgroundColor(IndentLevel, IsHovered);
}
void SExpanderArrow::Construct(const FArguments& InArgs, TSharedRef<ITableRow> DetailsRow)
{
Row = DetailsRow;
HasChildren = InArgs._HasChildren;
ChildSlot
[
SNew(SOverlay)
+ SOverlay::Slot()
[
SNew(SBorder)
.BorderImage(FAppStyle::Get().GetBrush("DetailsView.CategoryMiddle"))
.BorderBackgroundColor_Static(
PropertyInfoViewStyle::GetRowBackgroundColor,
Row.Pin().Get()
)
[
SNew(SBox)
.WidthOverride(20.0f)
.HeightOverride(16.0f)
]
]
+ SOverlay::Slot()
[
SAssignNew(ExpanderArrow, SButton)
.ButtonStyle(FCoreStyle::Get(), "NoBorder")
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.ClickMethod(EButtonClickMethod::MouseDown)
.OnClicked(this, &SExpanderArrow::OnExpanderClicked)
.ContentPadding(FMargin(0.0f))
.IsFocusable(false)
[
SNew(SImage)
.Image(this, &SExpanderArrow::GetExpanderImage)
.ColorAndOpacity(FSlateColor::UseForeground())
]
]
];
}
EVisibility SExpanderArrow::GetExpanderVisibility() const
{
TSharedPtr<ITableRow> RowPtr = Row.Pin();
if (!RowPtr.IsValid())
{
return EVisibility::Collapsed;
}
return RowPtr->DoesItemHaveChildren() ? EVisibility::Visible : EVisibility::Collapsed;
}
const FSlateBrush* SExpanderArrow::GetExpanderImage() const
{
TSharedPtr<ITableRow> RowPtr = Row.Pin();
if (!RowPtr.IsValid() || !HasChildren.Get())
{
return FAppStyle::Get().GetBrush("NoBrush");
}
const bool bIsItemExpanded = RowPtr->IsItemExpanded();
FName ResourceName;
if (bIsItemExpanded)
{
if (ExpanderArrow->IsHovered())
{
ResourceName = TEXT("TreeArrow_Expanded_Hovered");
}
else
{
ResourceName = TEXT("TreeArrow_Expanded");
}
}
else
{
if (ExpanderArrow->IsHovered())
{
ResourceName = TEXT("TreeArrow_Collapsed_Hovered");
}
else
{
ResourceName = TEXT("TreeArrow_Collapsed");
}
}
return FAppStyle::Get().GetBrush(ResourceName);
}
FReply SExpanderArrow::OnExpanderClicked() const
{
TSharedPtr<ITableRow> RowPtr = Row.Pin();
if (!RowPtr.IsValid())
{
return FReply::Unhandled();
}
// Recurse the expansion if "shift" is being pressed
const FModifierKeysState ModKeyState = FSlateApplication::Get().GetModifierKeys();
if (ModKeyState.IsShiftDown())
{
RowPtr->Private_OnExpanderArrowShiftClicked();
}
else
{
RowPtr->ToggleExpansion();
}
return FReply::Handled();
}
void STextHighlightOverlay::Construct(const FArguments& InArgs)
{
static FSlateBrush HighlightShape = FSlateBrush(*FAppStyle::Get().GetBrush("TextBlock.HighlightShape"));
HighlightShape.TintColor = FLinearColor(0.f, 0.47f, 1.f, .3f);
// uses overlay to create the highlight so that the text widget can be a button,
// hyperlink, textblock, etc
ChildSlot
[
SNew(SOverlay)
+SOverlay::Slot()
[
SNew(STextBlock)
.Text(InArgs._FullText)
.ColorAndOpacity(FLinearColor::Transparent)
.HighlightShape(&HighlightShape)
.HighlightText(InArgs._HighlightText)
]
+SOverlay::Slot()
[
InArgs._Content.Widget
]
];
}
}