Files
UnrealEngineUWP/Engine/Source/Editor/SourceControlWindows/Private/SSourceControlDescription.cpp
julien lheureux e1004780ae Added timer on changelist refresh operation
Added Move files operation on files in changelist dialog (incl. move to new)
Added new changelist button in toolbar
Added cancellable "path beautification" when we have deleted/shelved files with no matching file, until we make it lazy and/or batched

#rb sebastien.lussier

[CL 15797238 by julien lheureux in ue5-main branch]
2021-03-24 08:29:57 -04:00

283 lines
7.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SSourceControlDescription.h"
#include "Widgets/Layout/SUniformGridPanel.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Input/SComboButton.h"
#include "EditorStyleSet.h"
#include "Framework/Application/SlateApplication.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#define LOCTEXT_NAMESPACE "SourceControl.Description"
void SSourceControlDescriptionWidget::Construct(const FArguments& InArgs)
{
ParentWindow = InArgs._ParentWindow.Get();
Items = InArgs._Items;
const bool bHasItems = (Items && Items->Num() > 0);
const bool bShowSelectionDropDown = bHasItems;
const bool bDescriptionCanBeEdited = (!bHasItems || (*Items)[0].bCanEditDescription);
const bool bSelectTextWhenFocused = !bHasItems;
CurrentlySelectedItemIndex = 0;
ChildSlot
[
SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(16)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
.AutoWidth()
[
SNew(STextBlock)
.Text(InArgs._Label)
]
+ SHorizontalBox::Slot()
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
.Padding(8, 0, 0, 0)
[
SNew(SComboButton)
.Visibility(bShowSelectionDropDown ? EVisibility::Visible : EVisibility::Hidden)
.OnGetMenuContent(this, &SSourceControlDescriptionWidget::GetSelectionContent)
.ButtonContent()
[
SNew(STextBlock)
.Text(this, &SSourceControlDescriptionWidget::GetSelectedItemTitle)
]
]
]
+ SVerticalBox::Slot()
.Padding(FMargin(16, 0, 16, 16))
[
SAssignNew(TextBox, SMultiLineEditableTextBox)
.SelectAllTextWhenFocused(bSelectTextWhenFocused)
.IsReadOnly(!bDescriptionCanBeEdited)
.AutoWrapText(true)
.Text(InArgs._Text)
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(16)
[
SNew(SUniformGridPanel)
.SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding"))
.MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
.MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight"))
+SUniformGridPanel::Slot(0,0)
[
SNew(SButton)
.HAlign(HAlign_Center)
.ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
.Text( NSLOCTEXT("SourceControl.Description", "OKButton", "Ok") )
.OnClicked(this, &SSourceControlDescriptionWidget::OKClicked)
]
+SUniformGridPanel::Slot(1,0)
[
SNew(SButton)
.HAlign(HAlign_Center)
.ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
.Text( NSLOCTEXT("SourceControl.Description", "CancelButton", "Cancel") )
.OnClicked(this, &SSourceControlDescriptionWidget::CancelClicked)
]
]
]
];
ParentWindow.Pin()->SetWidgetToFocusOnActivate(TextBox);
}
FReply SSourceControlDescriptionWidget::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
// Pressing escape returns as if the user clicked cancel
if (InKeyEvent.GetKey() == EKeys::Escape)
{
return CancelClicked();
}
return FReply::Unhandled();
}
FReply SSourceControlDescriptionWidget::OKClicked()
{
bResult = true;
ParentWindow.Pin()->RequestDestroyWindow();
return FReply::Handled();
}
FReply SSourceControlDescriptionWidget::CancelClicked()
{
bResult = false;
ParentWindow.Pin()->RequestDestroyWindow();
return FReply::Handled();
}
FText SSourceControlDescriptionWidget::GetDescription() const
{
return TextBox->GetText();
}
static FText GetTitleAndShortDescription(const FText& InTitle, const FText& InDescription)
{
if (InDescription.IsEmptyOrWhitespace())
{
return InTitle;
}
else
{
FString TrimmedDescription = InDescription.ToString();
const int32 TrimmedMaxLen = 50;
if (TrimmedDescription.Len() > TrimmedMaxLen)
{
TrimmedDescription = TrimmedDescription.Left(TrimmedMaxLen);
TrimmedDescription += TEXT("...");
}
TrimmedDescription.ReplaceInline(TEXT("\r"), TEXT(""));
TrimmedDescription.ReplaceInline(TEXT("\n"), TEXT(" "));
FString TitleAndShortDescription = InTitle.ToString();
TitleAndShortDescription += TEXT(": ");
TitleAndShortDescription += TrimmedDescription;
return FText::FromString(TitleAndShortDescription);
}
}
FText SSourceControlDescriptionWidget::GetSelectedItemTitle() const
{
if (CurrentlySelectedItemIndex >= 0 && Items && CurrentlySelectedItemIndex < Items->Num())
{
const SSourceControlDescriptionItem& Item = (*Items)[CurrentlySelectedItemIndex];
return GetTitleAndShortDescription(Item.Title, Item.Description);
}
else
{
return LOCTEXT("SourceControlDescription_InvalidItemTitle", "Invalid");
}
}
TSharedRef<SWidget> SSourceControlDescriptionWidget::GetSelectionContent()
{
if (!Items || Items->Num() == 0)
{
return SNullWidget::NullWidget;
}
FMenuBuilder MenuBuilder(true, nullptr);
for(int32 ItemIndex = 0; ItemIndex < Items->Num(); ++ItemIndex)
{
const SSourceControlDescriptionItem& Item = (*Items)[ItemIndex];
MenuBuilder.AddMenuEntry(
GetTitleAndShortDescription(Item.Title, Item.Description),
FText(),
FSlateIcon(),
FUIAction(
FExecuteAction::CreateLambda([this, ItemIndex, &Item]() {
TextBox->SetIsReadOnly(!Item.bCanEditDescription);
TextBox->SetText(Item.Description);
CurrentlySelectedItemIndex = ItemIndex;
})),
NAME_None
);
}
return MenuBuilder.MakeWidget();
}
bool GetChangelistDescription(
const TSharedPtr<SWidget>& ParentWidget,
const FText& InWindowTitle,
const FText& InLabel,
FText& OutDescription)
{
FText InitialDescription = OutDescription;
if (InitialDescription.IsEmpty())
{
InitialDescription = LOCTEXT("SourceControl.NewDescription", "<enter description here>");
}
TSharedRef<SWindow> NewWindow = SNew(SWindow)
.Title(InWindowTitle)
.SizingRule(ESizingRule::UserSized)
.ClientSize(FVector2D(600, 400))
.SupportsMaximize(true)
.SupportsMinimize(false);
TSharedRef<SSourceControlDescriptionWidget> SourceControlWidget =
SNew(SSourceControlDescriptionWidget)
.ParentWindow(NewWindow)
.Label(InLabel)
.Text(InitialDescription);
NewWindow->SetContent(SourceControlWidget);
FSlateApplication::Get().AddModalWindow(NewWindow, ParentWidget);
if (SourceControlWidget->GetResult())
{
OutDescription = SourceControlWidget->GetDescription();
}
return SourceControlWidget->GetResult();
}
bool PickChangelistOrNewWithDescription(
const TSharedPtr<SWidget>& ParentWidget,
const FText& InWindowTitle,
const FText& InLabel,
const TArray<SSourceControlDescriptionItem>& Items,
int32& OutPickedIndex,
FText& OutDescription)
{
if (Items.Num() == 0)
{
return false;
}
TSharedRef<SWindow> NewWindow = SNew(SWindow)
.Title(InWindowTitle)
.SizingRule(ESizingRule::UserSized)
.ClientSize(FVector2D(600, 400))
.SupportsMaximize(true)
.SupportsMinimize(false);
TSharedRef<SSourceControlDescriptionWidget> SourceControlWidget =
SNew(SSourceControlDescriptionWidget)
.ParentWindow(NewWindow)
.Label(InLabel)
.Text(Items[0].Description)
.Items(&Items);
NewWindow->SetContent(SourceControlWidget);
FSlateApplication::Get().AddModalWindow(NewWindow, ParentWidget);
if (SourceControlWidget->GetResult())
{
OutPickedIndex = SourceControlWidget->GetSelectedItemIndex();
OutDescription = SourceControlWidget->GetDescription();
}
return SourceControlWidget->GetResult();
}
#undef LOCTEXT_NAMESPACE