Files
UnrealEngineUWP/Engine/Source/Developer/SourceControl/Private/SSourceControlControls.cpp

454 lines
14 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#if SOURCE_CONTROL_WITH_SLATE
#include "SSourceControlControls.h"
#include "ISourceControlProvider.h"
#include "ISourceControlModule.h"
#include "Misc/ConfigCacheIni.h"
#include "RevisionControlStyle/RevisionControlStyle.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Input/SComboBox.h"
#include "Widgets/Layout/SSeparator.h"
#define LOCTEXT_NAMESPACE "SSkeinSourceControlWidgets"
bool SSourceControlControls::bStaticDisableCheckInChangesOverride = false;
bool SSourceControlControls::bStaticDisableSyncLatestOverride = false;
FOnClicked SSourceControlControls::OnSyncLatestClickedStaticOverride;
/**
* Construct this widget
*
* @param InArgs The declaration data for this widget
*/
void SSourceControlControls::Construct(const FArguments& InArgs)
{
OnSyncLatestClicked = InArgs._OnClickedSyncLatest;
OnCheckInChangesClicked = InArgs._OnClickedCheckInChanges;
IsSyncLatestEnabled = InArgs._IsEnabledSyncLatest;
IsCheckInChangesEnabled = InArgs._IsEnabledCheckInChanges;
IsSyncLatestSeparatorEnabled = InArgs._IsEnabledSyncLatestSeparator;
IsCheckInChangesSeparatorEnabled = InArgs._IsEnabledCheckInChangesSeparator;
ChildSlot
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot() // Check In Changes Button
.VAlign(VAlign_Center)
.Padding(FMargin(0.0f, 0.0f, 4.0f, 0.0f))
.AutoWidth()
[
SNew(SButton)
.ButtonStyle(&FAppStyle::Get().GetWidgetStyle<FButtonStyle>("StatusBar.StatusBarButton"))
.ToolTipText(this, &SSourceControlControls::GetSourceControlCheckInStatusTooltipText)
.Visibility(this, &SSourceControlControls::GetSourceControlCheckInStatusVisibility)
.IsEnabled(this, &SSourceControlControls::IsSourceControlCheckInEnabled)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
[
SNew(SImage)
.Image(this, &SSourceControlControls::GetSourceControlCheckInStatusIcon)
]
+ SHorizontalBox::Slot()
.AutoWidth()
.VAlign(VAlign_Center)
.Padding(FMargin(5, 0, 0, 0))
[
SNew(STextBlock)
.TextStyle(&FAppStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText"))
.Text(this, &SSourceControlControls::GetSourceControlCheckInStatusText)
]
]
.OnClicked(this, &SSourceControlControls::OnSourceControlCheckInChangesClicked)
]
+SHorizontalBox::Slot() // Check In Kebab Combo button
.VAlign(VAlign_Center)
.AutoWidth()
[
SNew(SComboButton)
.ContentPadding(FMargin(7.f, 0.f))
.ComboButtonStyle(&FAppStyle::Get().GetWidgetStyle<FComboButtonStyle>("StatusBar.StatusBarEllipsisComboButton"))
.MenuPlacement(MenuPlacement_AboveAnchor)
.Visibility(this, &SSourceControlControls::GetSourceControlCheckInStatusVisibility)
.OnGetMenuContent(InArgs._OnGenerateKebabMenu)
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.AutoWidth()
[
SNew(SSeparator)
.Visibility(this, &SSourceControlControls::GetSourceControlCheckInSeparatorVisibility)
.Thickness(1.0)
.Orientation(EOrientation::Orient_Vertical)
]
+ SHorizontalBox::Slot() // Sync Latest Button
.VAlign(VAlign_Center)
.AutoWidth()
[
SNew(SButton)
.ButtonStyle(&FAppStyle::Get().GetWidgetStyle<FButtonStyle>("StatusBar.StatusBarButton"))
.ToolTipText(this, &SSourceControlControls::GetSourceControlSyncStatusTooltipText)
.Visibility(this, &SSourceControlControls::GetSourceControlSyncStatusVisibility)
.IsEnabled(this, &SSourceControlControls::IsSourceControlSyncEnabled)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
[
SNew(SImage)
.Image(this, &SSourceControlControls::GetSourceControlSyncStatusIcon)
]
+ SHorizontalBox::Slot()
.AutoWidth()
.VAlign(VAlign_Center)
.Padding(FMargin(5, 0, 0, 0))
[
SNew(STextBlock)
.TextStyle(&FAppStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText"))
.Text(this, &SSourceControlControls::GetSourceControlSyncStatusText)
]
]
.OnClicked(this, &SSourceControlControls::OnSourceControlSyncClicked)
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.AutoWidth()
[
SNew(SSeparator)
.Visibility(this, &SSourceControlControls::GetSourceControlSyncSeparatorVisibility)
.Thickness(1.0)
.Orientation(EOrientation::Orient_Vertical)
]
];
CheckSourceControlStatus();
}
void SSourceControlControls::CheckSourceControlStatus()
{
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
if (!SourceControlProviderChangedHandle.IsValid())
{
SourceControlProviderChangedHandle = SourceControlModule.RegisterProviderChanged(
FSourceControlProviderChanged::FDelegate::CreateSP(this, &SSourceControlControls::OnSourceControlProviderChanged)
);
SourceControlStateChangedHandle = SourceControlModule.GetProvider().RegisterSourceControlStateChanged_Handle(
FSourceControlStateChanged::FDelegate::CreateSP(this, &SSourceControlControls::OnSourceControlStateChanged)
);
}
}
void SSourceControlControls::OnSourceControlProviderChanged(ISourceControlProvider& OldProvider, ISourceControlProvider& NewProvider)
{
if (SourceControlStateChangedHandle.IsValid())
{
OldProvider.UnregisterSourceControlStateChanged_Handle(SourceControlStateChangedHandle);
SourceControlStateChangedHandle.Reset();
}
if (!IsEngineExitRequested())
{
SourceControlStateChangedHandle = NewProvider.RegisterSourceControlStateChanged_Handle(
FSourceControlStateChanged::FDelegate::CreateSP(this, &SSourceControlControls::OnSourceControlStateChanged)
);
}
}
void SSourceControlControls::OnSourceControlStateChanged()
{
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
TArray<FSourceControlStateRef> Conflicts = SourceControlProvider.GetCachedStateByPredicate(
[](const FSourceControlStateRef& State)
{
return State->IsConflicted();
}
);
NumConflictsRemaining = Conflicts.Num();
bConflictsRemaining = (NumConflictsRemaining > 0);
}
bool SSourceControlControls::AreConflictsRemaining() const
{
const bool bExiting = IsEngineExitRequested();
if (!bExiting)
{
return bConflictsRemaining;
}
return false;
}
int32 SSourceControlControls::GetNumConflictsRemaining() const
{
return NumConflictsRemaining;
}
/** Sync Status */
bool SSourceControlControls::IsAtLatestRevision() const
{
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
return SourceControlModule.IsEnabled() &&
SourceControlModule.GetProvider().IsAvailable() &&
SourceControlModule.GetProvider().IsAtLatestRevision().IsSet() &&
SourceControlModule.GetProvider().IsAtLatestRevision().GetValue();
}
bool SSourceControlControls::IsSourceControlSyncEnabled() const
{
if (!HasSourceControlChangesToSync())
{
return false;
}
return IsSyncLatestEnabled.Get(true) && !bStaticDisableSyncLatestOverride;
}
bool SSourceControlControls::HasSourceControlChangesToSync() const
{
return !IsAtLatestRevision();
}
EVisibility SSourceControlControls::GetSourceControlSyncStatusVisibility() const
{
if (!GIsEditor)
{
// Always visible in the Slate Viewer
return EVisibility::Visible;
}
bool bDisplaySourceControlSyncStatus = false;
GConfig->GetBool(TEXT("SourceControlSettings"), TEXT("DisplaySourceControlSyncStatus"), bDisplaySourceControlSyncStatus, GEditorIni);
if (bDisplaySourceControlSyncStatus)
{
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
if (SourceControlModule.IsEnabled() &&
SourceControlModule.GetProvider().IsAvailable() &&
SourceControlModule.GetProvider().IsAtLatestRevision().IsSet()) // Only providers that implement IsAtLatestRevision are supported.
{
return EVisibility::Visible;
}
}
return EVisibility::Collapsed;
}
EVisibility SSourceControlControls::GetSourceControlSyncSeparatorVisibility() const
{
EVisibility StatusVisibility = GetSourceControlSyncStatusVisibility();
if (StatusVisibility != EVisibility::Visible)
{
return StatusVisibility;
}
return IsSyncLatestSeparatorEnabled.Get(true) ? EVisibility::Visible : EVisibility::Collapsed;
}
FText SSourceControlControls::GetSourceControlSyncStatusText() const
{
if (HasSourceControlChangesToSync())
{
return LOCTEXT("SyncLatestButtonNotAtHeadText", "Sync Latest");
}
return LOCTEXT("SyncLatestButtonAtHeadText", "At Latest");
}
FText SSourceControlControls::GetSourceControlSyncStatusTooltipText() const
{
if (AreConflictsRemaining())
{
return LOCTEXT("SyncLatestButtonNotAtHeadTooltipTextConflict", "Some of your local changes conflict with the latest snapshot of the project. Click here to review these conflicts.");
}
if (HasSourceControlChangesToSync())
{
return LOCTEXT("SyncLatestButtonNotAtHeadTooltipText", "Sync to the latest Snapshot for this project");
}
return LOCTEXT("SyncLatestButtonAtHeadTooltipText", "Currently at the latest Snapshot for this project");
}
const FSlateBrush* SSourceControlControls::GetSourceControlSyncStatusIcon() const
{
static const FSlateBrush* ConflictBrush = FRevisionControlStyleManager::Get().GetBrush("RevisionControl.StatusBar.Conflicted");
static const FSlateBrush* AtHeadBrush = FRevisionControlStyleManager::Get().GetBrush("RevisionControl.StatusBar.AtLatestRevision");
static const FSlateBrush* NotAtHeadBrush = FRevisionControlStyleManager::Get().GetBrush("RevisionControl.StatusBar.NotAtLatestRevision");
if (AreConflictsRemaining())
{
return ConflictBrush;
}
if (HasSourceControlChangesToSync())
{
return NotAtHeadBrush;
}
return AtHeadBrush;
}
FReply SSourceControlControls::OnSourceControlSyncClicked() const
{
if (AreConflictsRemaining())
{
if (IConsoleObject* CObj = IConsoleManager::Get().FindConsoleObject(TEXT("UnrealRevisionControl.FocusConflictResolution")))
{
CObj->AsCommand()->Execute(/*Args=*/TArray<FString>(), /*InWorld=*/nullptr, *GLog);
}
}
else if (HasSourceControlChangesToSync())
{
if (OnSyncLatestClickedStaticOverride.IsBound())
{
OnSyncLatestClickedStaticOverride.Execute();
}
else if (OnSyncLatestClicked.IsBound())
{
OnSyncLatestClicked.Execute();
}
}
return FReply::Handled();
}
/** Check-in Status */
int SSourceControlControls::GetNumLocalChanges() const
{
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
if (SourceControlModule.IsEnabled() &&
SourceControlModule.GetProvider().IsAvailable() &&
SourceControlModule.GetProvider().GetNumLocalChanges().IsSet())
{
return SourceControlModule.GetProvider().GetNumLocalChanges().GetValue();
}
return 0;
}
bool SSourceControlControls::IsSourceControlCheckInEnabled() const
{
if (!HasSourceControlChangesToCheckIn())
{
return false;
}
return IsCheckInChangesEnabled.Get(true) && !bStaticDisableCheckInChangesOverride;
}
bool SSourceControlControls::HasSourceControlChangesToCheckIn() const
{
return (GetNumLocalChanges() > 0);
}
EVisibility SSourceControlControls::GetSourceControlCheckInStatusVisibility() const
{
if (!GIsEditor)
{
// Always visible in the Slate Viewer
return EVisibility::Visible;
}
bool bDisplaySourceControlCheckInStatus = false;
GConfig->GetBool(TEXT("SourceControlSettings"), TEXT("DisplaySourceControlCheckInStatus"), bDisplaySourceControlCheckInStatus, GEditorIni);
if (bDisplaySourceControlCheckInStatus)
{
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
if (SourceControlModule.IsEnabled() &&
SourceControlModule.GetProvider().IsAvailable() &&
SourceControlModule.GetProvider().GetNumLocalChanges().IsSet()) // Only providers that implement GetNumLocalChanges are supported.
{
return EVisibility::Visible;
}
}
return EVisibility::Collapsed;
}
EVisibility SSourceControlControls::GetSourceControlCheckInSeparatorVisibility() const
{
EVisibility StatusVisibility = GetSourceControlCheckInStatusVisibility();
if (StatusVisibility != EVisibility::Visible)
{
return StatusVisibility;
}
return IsCheckInChangesSeparatorEnabled.Get(true) ? EVisibility::Visible : EVisibility::Collapsed;
}
FText SSourceControlControls::GetSourceControlCheckInStatusText() const
{
if (HasSourceControlChangesToCheckIn())
{
return LOCTEXT("CheckInButtonChangesText", "Check-in Changes");
}
return LOCTEXT("CheckInButtonNoChangesText", "No Changes");
}
FText SSourceControlControls::GetSourceControlCheckInStatusTooltipText() const
{
if (AreConflictsRemaining())
{
return LOCTEXT("CheckInButtonChangesTooltipTextConflict", "Some of your local changes conflict with the latest snapshot of the project. Click here to review these conflicts.");
}
if (HasSourceControlChangesToCheckIn())
{
if (bStaticDisableCheckInChangesOverride)
{
return LOCTEXT("CheckInButtonChangesTooltipTextDisabled", "Check-in disabled while in a rewound state.");
}
return FText::Format(LOCTEXT("CheckInButtonChangesTooltipText", "Check-in {0} change(s) to this project"), GetNumLocalChanges());
}
return LOCTEXT("CheckInButtonNoChangesTooltipText", "No Changes to check in for this project");
}
const FSlateBrush* SSourceControlControls::GetSourceControlCheckInStatusIcon() const
{
static const FSlateBrush* ConflictBrush = FRevisionControlStyleManager::Get().GetBrush("RevisionControl.StatusBar.Conflicted");
static const FSlateBrush* NoLocalChangesBrush = FRevisionControlStyleManager::Get().GetBrush("RevisionControl.StatusBar.NoLocalChanges");
static const FSlateBrush* HasLocalChangesBrush = FRevisionControlStyleManager::Get().GetBrush("RevisionControl.StatusBar.HasLocalChanges");
if (AreConflictsRemaining())
{
return ConflictBrush;
}
if (HasSourceControlChangesToCheckIn())
{
return HasLocalChangesBrush;
}
return NoLocalChangesBrush;
}
FReply SSourceControlControls::OnSourceControlCheckInChangesClicked() const
{
if (AreConflictsRemaining())
{
if (IConsoleObject* CObj = IConsoleManager::Get().FindConsoleObject(TEXT("UnrealRevisionControl.FocusConflictResolution")))
{
CObj->AsCommand()->Execute(/*Args=*/TArray<FString>(), /*InWorld=*/nullptr, *GLog);
}
}
else if (HasSourceControlChangesToCheckIn())
{
if (OnCheckInChangesClicked.IsBound())
{
OnCheckInChangesClicked.Execute();
}
}
return FReply::Handled();
}
#undef LOCTEXT_NAMESPACE
#endif // SOURCE_CONTROL_WITH_SLATE