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

139 lines
4.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SRenameWindow.h"
#include "Framework/Application/SlateApplication.h"
#include "Interfaces/IMainFrameModule.h"
#include "Widgets/Input/SEditableTextBox.h"
#define LOCTEXT_NAMESPACE "SRenameWindow"
/**
* EditableTextBox used by the SRenameWindow
*/
class SRenameEditableTextBox : public SEditableTextBox
{
SLATE_BEGIN_ARGS(SRenameEditableTextBox)
{}
SLATE_EVENT(FOnTextCommitted, OnTextCommitted)
SLATE_EVENT(FOnVerifyTextChanged, OnVerifyTextChanged)
SLATE_ARGUMENT(FText, InitialText)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs, TSharedRef<SWindow> InOwnerWindow)
{
OwnerWindow = InOwnerWindow;
OnRenameCommittedDelegate = InArgs._OnTextCommitted;
SEditableTextBox::Construct(SEditableTextBox::FArguments()
.SelectAllTextWhenFocused(true)
.OnVerifyTextChanged(InArgs._OnVerifyTextChanged)
.Text(InArgs._InitialText)
.OnTextCommitted(this, &SRenameEditableTextBox::OnRenameTextCommitted));
}
void EndRename(bool bForceRename = false)
{
if (!bOnTextCommittedCalled)
{
bOnTextCommittedCalled = true;
OnRenameCommittedDelegate.ExecuteIfBound(GetText(), bForceRename ? ETextCommit::OnEnter : ETextCommit::OnCleared);
}
}
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override
{
if (InKeyEvent.GetKey() == EKeys::Escape)
{
EndRename();
if (const TSharedPtr<SWindow>& Window = OwnerWindow.Pin())
{
Window->RequestDestroyWindow();
}
return FReply::Handled();
}
return SEditableTextBox::OnKeyDown(MyGeometry, InKeyEvent);
}
private:
void OnRenameTextCommitted(const FText& InText, ETextCommit::Type InCommitType)
{
if (!bOnTextCommittedCalled)
{
bOnTextCommittedCalled = true;
OnRenameCommittedDelegate.ExecuteIfBound(InText, InCommitType);
if (const TSharedPtr<SWindow>& Window = OwnerWindow.Pin())
{
Window->RequestDestroyWindow();
}
}
}
private:
/** The OwnerWindow of this Widget */
TWeakPtr<SWindow> OwnerWindow;
/** Callback to call during the text OnCommitted callback */
FOnTextCommitted OnRenameCommittedDelegate;
/** Will be set to true once the OnCommitted is called once, there are cases which is called more time, but we want to call the passed callback just once */
bool bOnTextCommittedCalled = false;
};
void SRenameWindow::Construct(const FArguments& InArgs)
{
float DPIScale = 1.f;
{
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
const TSharedPtr<SWindow>& MainFrameParentWindow = MainFrameModule.GetParentWindow();
if (MainFrameParentWindow.IsValid())
{
DPIScale = MainFrameParentWindow->GetDPIScaleFactor();
}
}
const float AppScale = FSlateApplication::Get().GetApplicationScale();
constexpr float RenameWindowMinWidth = 100.f;
constexpr float RenameWindowFixedHeight = 30.f;
SWindow::Construct(SWindow::FArguments()
.SizingRule(ESizingRule::Autosized)
.AutoCenter(EAutoCenter::None)
.ScreenPosition(InArgs._ScreenPosition * (1.f/DPIScale))
.Type(EWindowType::Normal)
.LayoutBorder(0)
.ActivationPolicy(EWindowActivationPolicy::FirstShown)
.bDragAnywhere(false)
.CreateTitleBar(false)
.FocusWhenFirstShown(true)
.MinWidth(RenameWindowMinWidth * AppScale * DPIScale)
.MinHeight(RenameWindowFixedHeight * AppScale * DPIScale)
.MaxHeight(RenameWindowFixedHeight * AppScale * DPIScale)
[
SAssignNew(RenameEditableTextBox, SRenameEditableTextBox, StaticCastSharedRef<SWindow>(AsShared()))
.OnVerifyTextChanged(InArgs._OnVerifyTextChanged)
.InitialText(InArgs._InitialText)
.OnTextCommitted(InArgs._OnTextCommitted)
]);
// Once you open the SRenameWindow call the OnBeginText already since that is the moment where the Rename begin
InArgs._OnBeginTextEdit.ExecuteIfBound(InArgs._InitialText);
SetWidgetToFocusOnActivate(RenameEditableTextBox);
OnWindowDeactivated.BindSP(this, &SRenameWindow::DeactivateWindow);
}
void SRenameWindow::DeactivateWindow()
{
if (RenameEditableTextBox.IsValid())
{
// Always force it when deactivating the window
// This will not rename when pressing ESC since the rename already happened with TextCommit = OnCleared
RenameEditableTextBox->EndRename(true);
}
RequestDestroyWindow();
}
#undef LOCTEXT_NAMESPACE