2022-05-25 16:27:45 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "StatusBarSubsystem.h"
# include "ToolMenus.h"
# include "Framework/Docking/TabManager.h"
# include "Framework/Application/SlateApplication.h"
# include "ContentBrowserModule.h"
# include "IContentBrowserSingleton.h"
# include "SourceControlMenuHelpers.h"
# include "SStatusBar.h"
# include "Widgets/Docking/SDockTab.h"
# include "Editor.h"
# include "Toolkits/GlobalEditorCommonCommands.h"
# include "Widgets/Notifications/SNotificationList.h"
# include "Framework/Notifications/NotificationManager.h"
# include "Interfaces/IMainFrameModule.h"
# include "Widgets/Notifications/SNotificationBackground.h"
# include "Brushes/SlateRoundedBoxBrush.h"
# include "Styling/StyleColors.h"
# include "Widgets/Images/SImage.h"
# include "Widgets/Input/SButton.h"
# include "Misc/ConfigCacheIni.h"
# include "OutputLogModule.h"
# include "WidgetDrawerConfig.h"
# include "Widgets/Input/SMultiLineEditableTextBox.h"
# include "OutputLog/Public/OutputLogSettings.h"
# define LOCTEXT_NAMESPACE "StatusBar"
DEFINE_LOG_CATEGORY_STATIC ( LogStatusBar , Log , All ) ;
int32 UStatusBarSubsystem : : MessageHandleCounter = 0 ;
namespace UE
{
namespace StatusBarSubsystem
{
namespace Private
{
TSharedPtr < SWindow > FindParentWindow ( )
{
TSharedPtr < SWindow > ParentWindow = FSlateApplication : : Get ( ) . GetActiveTopLevelWindow ( ) ;
if ( ! ParentWindow . IsValid ( ) )
{
if ( TSharedPtr < SDockTab > ActiveTab = FGlobalTabmanager : : Get ( ) - > GetActiveTab ( ) )
{
if ( TSharedPtr < FTabManager > ActiveTabManager = ActiveTab - > GetTabManagerPtr ( ) )
{
if ( TSharedPtr < SDockTab > ActiveMajorTab = FGlobalTabmanager : : Get ( ) - > GetMajorTabForTabManager ( ActiveTabManager . ToSharedRef ( ) ) )
{
ParentWindow = ActiveMajorTab - > GetParentWindow ( ) ;
}
}
}
}
return ParentWindow ;
}
}
}
}
class SNewUserTipNotification : public SCompoundWidget
{
SLATE_BEGIN_ARGS ( SNewUserTipNotification )
{ }
SLATE_END_ARGS ( )
SNewUserTipNotification ( )
: NewBadgeBrush ( FStyleColors : : Success )
, KeybindBackgroundBrush ( FLinearColor : : Transparent , 6.0f , FStyleColors : : ForegroundHover , 1.5f )
{ }
static void Show ( TSharedPtr < SWindow > InParentWindow )
{
if ( ! ActiveNotification . IsValid ( ) )
{
TSharedRef < SNewUserTipNotification > ActiveNotificationRef =
SNew ( SNewUserTipNotification ) ;
ActiveNotification = ActiveNotificationRef ;
ParentWindow = InParentWindow ;
InParentWindow - > AddOverlaySlot ( )
. VAlign ( VAlign_Bottom )
. HAlign ( HAlign_Left )
. Padding ( FMargin ( 20.0f , 20.0f , 10.0f , 50.f ) )
[
ActiveNotificationRef
] ;
}
}
static void Dismiss ( )
{
TSharedPtr < SNewUserTipNotification > ActiveNotificationPin = ActiveNotification . Pin ( ) ;
if ( ParentWindow . IsValid ( ) & & ActiveNotificationPin . IsValid ( ) )
{
ParentWindow . Pin ( ) - > RemoveOverlaySlot ( ActiveNotificationPin . ToSharedRef ( ) ) ;
}
ParentWindow . Reset ( ) ;
ActiveNotification . Reset ( ) ;
}
void Construct ( const FArguments & InArgs )
{
ChildSlot
[
SNew ( SBox )
. WidthOverride ( 350.0f )
. HeightOverride ( 128.0f )
[
SNew ( SNotificationBackground )
. Padding ( FMargin ( 16 , 8 ) )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. Padding ( 0.0f , 6.0f , 0.0f , 0.0f )
. VAlign ( VAlign_Top )
. AutoWidth ( )
[
SNew ( SBorder )
. Padding ( FMargin ( 11 , 4 ) )
. BorderImage ( & NewBadgeBrush )
. ForegroundColor ( FStyleColors : : ForegroundInverted )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " NewBadge " , " New " ) )
. TextStyle ( FAppStyle : : Get ( ) , " SmallButtonText " )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
]
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 16.0f , 8.0f , 0.0f , 0.0f )
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0.0f , 0.0f , 0.0f , 0.0f )
[
SNew ( STextBlock )
. Font ( FAppStyle : : Get ( ) . GetFontStyle ( " NotificationList.FontBold " ) )
. Text ( LOCTEXT ( " ContentDrawerTipTitle " , " Content Drawer " ) )
. ColorAndOpacity ( FStyleColors : : ForegroundHover )
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0.0f , 12.0f , 0.0f , 0.0f )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
SNew ( SBorder )
. Padding ( FMargin ( 20 , 4 ) )
. BorderImage ( & KeybindBackgroundBrush )
[
SNew ( STextBlock )
. TextStyle ( FAppStyle : : Get ( ) , " DialogButtonText " )
. Text ( FGlobalEditorCommonCommands : : Get ( ) . OpenContentBrowserDrawer - > GetActiveChord ( EMultipleKeyBindingIndex : : Primary ) - > GetModifierText ( FText : : GetEmpty ( ) ) )
. ColorAndOpacity ( FStyleColors : : ForegroundHover )
]
]
+ SHorizontalBox : : Slot ( )
. Padding ( 8.0f , 0.0f )
. AutoWidth ( )
. VAlign ( VAlign_Center )
[
SNew ( SImage )
. Image ( FAppStyle : : Get ( ) . GetBrush ( " Icons.Plus " ) )
. ColorAndOpacity ( FStyleColors : : ForegroundHover )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
SNew ( SBorder )
. Padding ( FMargin ( 20 , 4 ) )
. BorderImage ( & KeybindBackgroundBrush )
[
SNew ( STextBlock )
. TextStyle ( FAppStyle : : Get ( ) , " DialogButtonText " )
. Text ( FGlobalEditorCommonCommands : : Get ( ) . OpenContentBrowserDrawer - > GetActiveChord ( EMultipleKeyBindingIndex : : Primary ) - > Key . GetDisplayName ( false ) )
. ColorAndOpacity ( FStyleColors : : ForegroundHover )
]
]
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0.0f , 12.0f , 0.0f , 0.0f )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " ContentDrawerTipDesc " , " Summon the content browser in \n collapsable drawer. " ) )
. ColorAndOpacity ( FStyleColors : : Foreground )
]
]
+ SHorizontalBox : : Slot ( )
. Padding ( 0.0f , 0.0f , 0.0f , 0.0f )
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Top )
[
SNew ( SButton )
. ButtonStyle ( FAppStyle : : Get ( ) , " SimpleButton " )
. OnClicked_Lambda ( [ ] ( ) { SNewUserTipNotification : : Dismiss ( ) ; return FReply : : Handled ( ) ; } )
[
SNew ( SImage )
. Image ( FAppStyle : : Get ( ) . GetBrush ( " Icons.X " ) )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
]
]
]
]
] ;
}
private :
FSlateRoundedBoxBrush NewBadgeBrush ;
FSlateRoundedBoxBrush KeybindBackgroundBrush ;
static TWeakPtr < SNewUserTipNotification > ActiveNotification ;
static TWeakPtr < SWindow > ParentWindow ;
} ;
TWeakPtr < SNewUserTipNotification > SNewUserTipNotification : : ActiveNotification ;
TWeakPtr < SWindow > SNewUserTipNotification : : ParentWindow ;
void UStatusBarSubsystem : : Initialize ( FSubsystemCollectionBase & Collection )
{
FSourceControlCommands : : Register ( ) ;
IMainFrameModule & MainFrameModule = IMainFrameModule : : Get ( ) ;
if ( MainFrameModule . IsWindowInitialized ( ) )
{
CreateAndShowNewUserTipIfNeeded ( MainFrameModule . GetParentWindow ( ) , false ) ;
}
else
{
MainFrameModule . OnMainFrameCreationFinished ( ) . AddUObject ( this , & UStatusBarSubsystem : : CreateAndShowNewUserTipIfNeeded ) ;
}
FSlateNotificationManager : : Get ( ) . SetProgressNotificationHandler ( this ) ;
}
void UStatusBarSubsystem : : Deinitialize ( )
{
FSourceControlCommands : : Unregister ( ) ;
FSlateNotificationManager : : Get ( ) . SetProgressNotificationHandler ( nullptr ) ;
StatusBarContentBrowser . Reset ( ) ;
StatusBarOutputLog . Reset ( ) ;
}
bool UStatusBarSubsystem : : ToggleDebugConsole ( TSharedRef < SWindow > ParentWindow , bool bAlwaysToggleDrawer )
{
bool bToggledSuccessfully = false ;
FOutputLogModule & OutputLogModule = FOutputLogModule : : Get ( ) ;
// Get the global output log tab if it exists. If it exists and is in the same editor as the status bar we'll focus that instead
TSharedPtr < SDockTab > MainOutputLogTab = OutputLogModule . GetOutputLogTab ( ) ;
const bool bCycleToOutputLogDrawer = GetDefault < UOutputLogSettings > ( ) - > bCycleToOutputLogDrawer | | bAlwaysToggleDrawer ;
for ( auto StatusBar : StatusBars )
{
FStatusBarData & SBData = StatusBar . Value ;
if ( TSharedPtr < SStatusBar > StatusBarPinned = SBData . StatusBarWidget . Pin ( ) )
{
TSharedPtr < SDockTab > ParentTab = StatusBarPinned - > GetParentTab ( ) ;
if ( ParentTab & & ParentTab - > IsForeground ( ) & & ParentTab - > GetParentWindow ( ) = = ParentWindow )
{
FWidgetPath ConsoleEditBoxPath ;
if ( FSlateApplication : : Get ( ) . GeneratePathToWidgetUnchecked ( SBData . ConsoleEditBox . ToSharedRef ( ) , ConsoleEditBoxPath ) )
{
if ( bAlwaysToggleDrawer & & MainOutputLogTab & & MainOutputLogTab - > GetTabManagerPtr ( ) & & MainOutputLogTab - > GetTabManagerPtr ( ) - > GetOwnerTab ( ) = = ParentTab )
{
OutputLogModule . FocusOutputLogConsoleBox ( OutputLogModule . GetOutputLog ( ) . ToSharedRef ( ) ) ;
}
else
{
// This toggles between 3 states:
// If the drawer is opened, close it
// if the console edit box is focused, open the drawer
// if something else is focused, focus the console edit box
if ( StatusBarPinned - > IsDrawerOpened ( StatusBarDrawerIds : : OutputLog ) )
{
StatusBarPinned - > DismissDrawer ( nullptr ) ;
}
else if ( SBData . ConsoleEditBox - > HasKeyboardFocus ( ) | | bAlwaysToggleDrawer )
{
if ( bCycleToOutputLogDrawer )
{
StatusBarPinned - > OpenDrawer ( StatusBarDrawerIds : : OutputLog ) ;
}
else
{
// Restore previous focus
FSlateApplication : : Get ( ) . SetKeyboardFocus ( PreviousKeyboardFocusedWidget . Pin ( ) , EFocusCause : : SetDirectly ) ;
PreviousKeyboardFocusedWidget . Reset ( ) ;
}
}
else
{
// Cache off the previously focused widget so we can restore focus if the user hits the focus key again
PreviousKeyboardFocusedWidget = FSlateApplication : : Get ( ) . GetKeyboardFocusedWidget ( ) ;
FSlateApplication : : Get ( ) . SetKeyboardFocus ( ConsoleEditBoxPath , EFocusCause : : SetDirectly ) ;
}
}
bToggledSuccessfully = true ;
break ;
}
}
}
}
return bToggledSuccessfully ;
}
bool UStatusBarSubsystem : : OpenContentBrowserDrawer ( )
{
TSharedPtr < SWindow > ParentWindow = UE : : StatusBarSubsystem : : Private : : FindParentWindow ( ) ;
if ( ParentWindow . IsValid ( ) & & ParentWindow - > GetType ( ) = = EWindowType : : Normal )
{
TSharedRef < SWindow > WindowRef = ParentWindow . ToSharedRef ( ) ;
return ToggleContentBrowser ( ParentWindow . ToSharedRef ( ) ) ;
}
return false ;
}
bool UStatusBarSubsystem : : OpenOutputLogDrawer ( )
{
TSharedPtr < SWindow > ParentWindow = UE : : StatusBarSubsystem : : Private : : FindParentWindow ( ) ;
if ( ParentWindow . IsValid ( ) & & ParentWindow - > GetType ( ) = = EWindowType : : Normal )
{
return ToggleDebugConsole ( ParentWindow . ToSharedRef ( ) , true ) ;
}
return false ;
}
bool UStatusBarSubsystem : : TryToggleDrawer ( const FName DrawerId )
{
bool bToggledSuccessfully = false ;
TSharedPtr < SWindow > ParentWindow = UE : : StatusBarSubsystem : : Private : : FindParentWindow ( ) ;
if ( ParentWindow . IsValid ( ) & & ParentWindow - > GetType ( ) = = EWindowType : : Normal )
{
for ( auto StatusBar : StatusBars )
{
FStatusBarData & SBData = StatusBar . Value ;
if ( TSharedPtr < SStatusBar > StatusBarPinned = SBData . StatusBarWidget . Pin ( ) )
{
TSharedPtr < SDockTab > ParentTab = StatusBarPinned - > GetParentTab ( ) ;
if ( ParentTab & & ParentTab - > IsForeground ( ) & & ParentTab - > GetParentWindow ( ) = = ParentWindow )
{
if ( StatusBarPinned - > IsDrawerOpened ( DrawerId ) )
{
StatusBarPinned - > DismissDrawer ( nullptr ) ;
}
else
{
StatusBarPinned - > OpenDrawer ( DrawerId ) ;
}
bToggledSuccessfully = true ;
break ;
}
}
}
}
return bToggledSuccessfully ;
}
bool UStatusBarSubsystem : : ForceDismissDrawer ( )
{
bool bWasDismissed = false ;
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
bWasDismissed | = StatusBarPinned - > DismissDrawer ( nullptr ) ;
}
}
return bWasDismissed ;
}
bool UStatusBarSubsystem : : ToggleContentBrowser ( TSharedRef < SWindow > ParentWindow )
{
bool bWasDismissed = false ;
SNewUserTipNotification : : Dismiss ( ) ;
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
if ( StatusBarPinned - > IsDrawerOpened ( StatusBarDrawerIds : : ContentBrowser ) )
{
TSharedPtr < SDockTab > ParentTab = StatusBarPinned - > GetParentTab ( ) ;
if ( ParentTab & & ParentTab - > IsForeground ( ) & & ParentTab - > GetParentWindow ( ) = = ParentWindow )
{
StatusBarPinned - > DismissDrawer ( nullptr ) ;
bWasDismissed = true ;
}
}
}
}
if ( ! bWasDismissed )
{
TSharedPtr < SWindow > Window = ParentWindow ;
GEditor - > GetTimerManager ( ) - > SetTimerForNextTick ( FTimerDelegate : : CreateUObject ( this , & UStatusBarSubsystem : : HandleDeferredOpenContentBrowser , Window ) ) ;
}
return true ;
}
TSharedRef < SWidget > UStatusBarSubsystem : : MakeStatusBarWidget ( FName StatusBarName , const TSharedRef < SDockTab > & InParentTab )
{
CreateContentBrowserIfNeeded ( ) ;
TSharedRef < SStatusBar > StatusBar =
SNew ( SStatusBar , StatusBarName , InParentTab ) ;
FWidgetDrawerConfig ContentBrowserDrawer ( StatusBarDrawerIds : : ContentBrowser ) ;
ContentBrowserDrawer . GetDrawerContentDelegate . BindUObject ( this , & UStatusBarSubsystem : : OnGetContentBrowser ) ;
ContentBrowserDrawer . OnDrawerOpenedDelegate . BindUObject ( this , & UStatusBarSubsystem : : OnContentBrowserOpened ) ;
ContentBrowserDrawer . OnDrawerDismissedDelegate . BindUObject ( this , & UStatusBarSubsystem : : OnContentBrowserDismissed ) ;
ContentBrowserDrawer . ButtonText = LOCTEXT ( " StatusBar_ContentBrowserButton " , " Content Drawer " ) ;
ContentBrowserDrawer . ToolTipText = FText : : Format ( LOCTEXT ( " StatusBar_ContentBrowserDrawerToolTip " , " Opens a temporary content browser above this status which will dismiss when it loses focus ({0}) " ) , FGlobalEditorCommonCommands : : Get ( ) . OpenContentBrowserDrawer - > GetInputText ( ) ) ;
ContentBrowserDrawer . Icon = FAppStyle : : Get ( ) . GetBrush ( " ContentBrowser.TabIcon " ) ;
StatusBar - > RegisterDrawer ( MoveTemp ( ContentBrowserDrawer ) ) ;
FOutputLogModule & OutputLogModule = FOutputLogModule : : Get ( ) ;
TWeakPtr < SStatusBar > StatusBarWeakPtr = StatusBar ;
FSimpleDelegate OnConsoleClosed = FSimpleDelegate : : CreateUObject ( this , & UStatusBarSubsystem : : OnDebugConsoleClosed , StatusBarWeakPtr ) ;
FSimpleDelegate OnConsoleCommandExecuted ;
TSharedPtr < SMultiLineEditableTextBox > ConsoleEditBox ;
TSharedRef < SWidget > OutputLog =
SNew ( SBorder )
. BorderImage ( FAppStyle : : Get ( ) . GetBrush ( " Brushes.Panel " ) )
. VAlign ( VAlign_Center )
. Padding ( FMargin ( 6.0f , 0.0f ) )
[
SNew ( SBox )
. WidthOverride ( 350.f )
[
OutputLogModule . MakeConsoleInputBox ( ConsoleEditBox , OnConsoleClosed , OnConsoleCommandExecuted )
]
] ;
FWidgetDrawerConfig OutputLogDrawer ( StatusBarDrawerIds : : OutputLog ) ;
OutputLogDrawer . GetDrawerContentDelegate . BindUObject ( this , & UStatusBarSubsystem : : OnGetOutputLog ) ;
OutputLogDrawer . OnDrawerOpenedDelegate . BindUObject ( this , & UStatusBarSubsystem : : OnOutputLogOpened ) ;
OutputLogDrawer . OnDrawerDismissedDelegate . BindUObject ( this , & UStatusBarSubsystem : : OnOutputLogDismised ) ;
OutputLogDrawer . CustomWidget = OutputLog ;
OutputLogDrawer . ButtonText = LOCTEXT ( " StatusBar_OutputLogButton " , " Output Log " ) ;
OutputLogDrawer . ToolTipText = FText : : Format ( LOCTEXT ( " StatusBar_OutputLogButtonTip " , " Opens the output log drawer. ({0}) cycles between focusing the console command box, opening the output log drawer, and closing it. \n The output log drawer may also be toggled directly with ({1}) " ) , FGlobalEditorCommonCommands : : Get ( ) . OpenConsoleCommandBox - > GetInputText ( ) , FGlobalEditorCommonCommands : : Get ( ) . OpenOutputLogDrawer - > GetInputText ( ) ) ;
OutputLogDrawer . Icon = FAppStyle : : Get ( ) . GetBrush ( " Log.TabIcon " ) ;
StatusBar - > RegisterDrawer ( MoveTemp ( OutputLogDrawer ) ) ;
// Clean up stale status bars
for ( auto It = StatusBars . CreateIterator ( ) ; It ; + + It )
{
if ( ! It . Value ( ) . StatusBarWidget . IsValid ( ) )
{
It . RemoveCurrent ( ) ;
}
}
FStatusBarData StatusBarData ;
StatusBarData . StatusBarWidget = StatusBar ;
StatusBarData . ConsoleEditBox = ConsoleEditBox ;
StatusBars . Add ( StatusBarName , StatusBarData ) ;
return StatusBar ;
}
bool UStatusBarSubsystem : : ActiveWindowHasStatusBar ( ) const
{
TSharedPtr < SWindow > ParentWindow = UE : : StatusBarSubsystem : : Private : : FindParentWindow ( ) ;
if ( ParentWindow . IsValid ( ) & & ParentWindow - > GetType ( ) = = EWindowType : : Normal )
{
for ( const TPair < FName , FStatusBarData > & StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
TSharedPtr < SDockTab > ParentTab = StatusBarPinned - > GetParentTab ( ) ;
if ( ParentTab & & ParentTab - > IsForeground ( ) & & ParentTab - > GetParentWindow ( ) = = ParentWindow )
{
return true ;
}
}
}
}
return false ;
}
void UStatusBarSubsystem : : RegisterDrawer ( FName StatusBarName , FWidgetDrawerConfig & & Drawer , int32 SlotIndex )
{
if ( TSharedPtr < SStatusBar > StatusBar = GetStatusBar ( StatusBarName ) )
{
StatusBar - > RegisterDrawer ( MoveTemp ( Drawer ) , SlotIndex ) ;
}
}
FStatusBarMessageHandle UStatusBarSubsystem : : PushStatusBarMessage ( FName StatusBarName , const TAttribute < FText > & InMessage , const TAttribute < FText > & InHintText )
{
if ( TSharedPtr < SStatusBar > StatusBar = GetStatusBar ( StatusBarName ) )
{
FStatusBarMessageHandle NewHandle ( + + MessageHandleCounter ) ;
StatusBar - > PushMessage ( NewHandle , InMessage , InHintText ) ;
return NewHandle ;
}
return FStatusBarMessageHandle ( ) ;
}
FStatusBarMessageHandle UStatusBarSubsystem : : PushStatusBarMessage ( FName StatusBarName , const TAttribute < FText > & InMessage )
{
return PushStatusBarMessage ( StatusBarName , InMessage , TAttribute < FText > ( ) ) ;
}
void UStatusBarSubsystem : : PopStatusBarMessage ( FName StatusBarName , FStatusBarMessageHandle InHandle )
{
if ( TSharedPtr < SStatusBar > StatusBar = GetStatusBar ( StatusBarName ) )
{
StatusBar - > PopMessage ( InHandle ) ;
}
}
void UStatusBarSubsystem : : ClearStatusBarMessages ( FName StatusBarName )
{
if ( TSharedPtr < SStatusBar > StatusBar = GetStatusBar ( StatusBarName ) )
{
StatusBar - > ClearAllMessages ( ) ;
}
}
void UStatusBarSubsystem : : StartProgressNotification ( FProgressNotificationHandle Handle , FText DisplayText , int32 TotalWorkToDo )
{
// Get the active window, if one is not active a notification was started when the application was deactivated so use the focus path to find a window or just use the root window if there is no keyboard focus
TSharedPtr < SWindow > ActiveWindow = FSlateApplication : : Get ( ) . GetActiveTopLevelRegularWindow ( ) ;
if ( ! ActiveWindow )
{
TSharedPtr < SWidget > FocusedWidget = FSlateApplication : : Get ( ) . GetKeyboardFocusedWidget ( ) ;
ActiveWindow = FocusedWidget ? FSlateApplication : : Get ( ) . FindWidgetWindow ( FocusedWidget . ToSharedRef ( ) ) : FGlobalTabmanager : : Get ( ) - > GetRootWindow ( ) ;
}
// Find the active status bar to display the progress in
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
TSharedPtr < SDockTab > ParentTab = StatusBarPinned - > GetParentTab ( ) ;
if ( ParentTab & & ParentTab - > IsForeground ( ) & & ParentTab - > GetParentWindow ( ) = = ActiveWindow )
{
StatusBarPinned - > StartProgressNotification ( Handle , DisplayText , TotalWorkToDo ) ;
break ;
}
}
}
}
void UStatusBarSubsystem : : UpdateProgressNotification ( FProgressNotificationHandle Handle , int32 TotalWorkDone , int32 UpdatedTotalWorkToDo , FText UpdatedDisplayText )
{
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
if ( StatusBarPinned - > UpdateProgressNotification ( Handle , TotalWorkDone , UpdatedTotalWorkToDo , UpdatedDisplayText ) )
{
break ;
}
}
}
}
void UStatusBarSubsystem : : CancelProgressNotification ( FProgressNotificationHandle Handle )
{
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
if ( StatusBarPinned - > CancelProgressNotification ( Handle ) )
{
break ;
}
}
}
}
void UStatusBarSubsystem : : OnDebugConsoleClosed ( TWeakPtr < SStatusBar > OwningStatusBar )
{
if ( TSharedPtr < SStatusBar > OwningStatusBarPinned = OwningStatusBar . Pin ( ) )
{
TSharedPtr < SWindow > OwningWindow = OwningStatusBarPinned - > GetParentTab ( ) - > GetParentWindow ( ) ;
ToggleDebugConsole ( OwningWindow . ToSharedRef ( ) ) ;
}
}
void UStatusBarSubsystem : : CreateContentBrowserIfNeeded ( )
{
if ( ! StatusBarContentBrowser . IsValid ( ) )
{
IContentBrowserSingleton & ContentBrowserSingleton = FModuleManager : : Get ( ) . LoadModuleChecked < FContentBrowserModule > ( " ContentBrowser " ) . Get ( ) ; ;
FContentBrowserConfig Config ;
Config . bCanSetAsPrimaryBrowser = true ;
TFunction < TSharedPtr < SDockTab > ( ) > GetTab (
[ this ] ( ) - > TSharedPtr < SDockTab >
{
UE_LOG ( LogStatusBar , Log , TEXT ( " Looking status bar with open content browser drawer... " ) )
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
if ( StatusBarPinned - > IsDrawerOpened ( StatusBarDrawerIds : : ContentBrowser ) )
{
UE_LOG ( LogStatusBar , Log , TEXT ( " Using status bar: %s to dock content browser " ) , * StatusBar . Key . ToString ( ) ) ;
return StatusBarPinned - > GetParentTab ( ) ;
}
else
{
UE_LOG ( LogStatusBar , Log , TEXT ( " StatusBar: %s was content browser was not opened " ) , * StatusBar . Key . ToString ( ) ) ;
}
}
}
ensureMsgf ( false , TEXT ( " If we get here somehow a content browser drawer is opened but no status bar claims it " ) ) ;
return TSharedPtr < SDockTab > ( ) ;
}
) ;
StatusBarContentBrowser = ContentBrowserSingleton . CreateContentBrowserDrawer ( Config , GetTab ) ;
}
}
void UStatusBarSubsystem : : CreateAndShowNewUserTipIfNeeded ( TSharedPtr < SWindow > ParentWindow , bool bIsNewProjectDialog )
{
if ( ! bIsNewProjectDialog )
{
const FString StoreId = TEXT ( " Epic Games " ) ;
const FString SectionName = TEXT ( " Unreal Engine/Editor " ) ;
const FString KeyName = TEXT ( " LaunchTipShown " ) ;
const FString FallbackIniLocation = TEXT ( " /Script/UnrealEd.EditorSettings " ) ;
const FString FallbackIniKey = TEXT ( " LaunchTipShownFallback " ) ;
// Its important that this new user message does not appear after the first launch so we store it in a more permanent place
FString CurrentState = TEXT ( " 0 " ) ;
if ( ! FPlatformMisc : : GetStoredValue ( StoreId , SectionName , KeyName , CurrentState ) )
{
// As a fallback where the registry was not readable or writable, save a flag in the editor ini. This will be less permanent as the registry but will prevent
// the notification from appearing on every launch
GConfig - > GetString ( * FallbackIniLocation , * FallbackIniKey , CurrentState , GEditorSettingsIni ) ;
}
if ( CurrentState ! = TEXT ( " 1 " ) )
{
SNewUserTipNotification : : Show ( ParentWindow ) ;
// Write that we've shown the notification
if ( ! FPlatformMisc : : SetStoredValue ( StoreId , SectionName , KeyName , TEXT ( " 1 " ) ) )
{
// Use fallback
GConfig - > SetString ( * FallbackIniLocation , * FallbackIniKey , TEXT ( " 1 " ) , GEditorSettingsIni ) ;
}
}
}
// Ignore the if the main frame gets recreated this session
IMainFrameModule : : Get ( ) . OnMainFrameCreationFinished ( ) . RemoveAll ( this ) ;
}
TSharedPtr < SStatusBar > UStatusBarSubsystem : : GetStatusBar ( FName StatusBarName ) const
{
return StatusBars . FindRef ( StatusBarName ) . StatusBarWidget . Pin ( ) ;
}
TSharedRef < SWidget > UStatusBarSubsystem : : OnGetContentBrowser ( )
{
CreateContentBrowserIfNeeded ( ) ;
return StatusBarContentBrowser . ToSharedRef ( ) ;
}
void UStatusBarSubsystem : : OnContentBrowserOpened ( FName StatusBarWithDrawerName )
{
SNewUserTipNotification : : Dismiss ( ) ;
// Dismiss any other content browser that is opened when one status bar opens it. The content browser is a shared resource and shouldn't be in the layout twice
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
if ( StatusBarWithDrawerName ! = StatusBarPinned - > GetStatusBarName ( ) | | StatusBarPinned - > IsAnyOtherDrawerOpened ( StatusBarDrawerIds : : ContentBrowser ) )
{
StatusBarPinned - > CloseDrawerImmediately ( ) ;
}
}
}
IContentBrowserSingleton & ContentBrowserSingleton = FModuleManager : : Get ( ) . LoadModuleChecked < FContentBrowserModule > ( " ContentBrowser " ) . Get ( ) ; ;
// Cache off the previously focused widget so we can restore focus if the user hits the focus key again
PreviousKeyboardFocusedWidget = FSlateApplication : : Get ( ) . GetKeyboardFocusedWidget ( ) ;
ContentBrowserSingleton . FocusContentBrowserSearchField ( StatusBarContentBrowser ) ;
}
void UStatusBarSubsystem : : OnContentBrowserDismissed ( const TSharedPtr < SWidget > & NewlyFocusedWidget )
{
if ( PreviousKeyboardFocusedWidget . IsValid ( ) & & ! NewlyFocusedWidget . IsValid ( ) )
{
FSlateApplication : : Get ( ) . SetKeyboardFocus ( PreviousKeyboardFocusedWidget . Pin ( ) ) ;
}
IContentBrowserSingleton & ContentBrowserSingleton = FModuleManager : : Get ( ) . LoadModuleChecked < FContentBrowserModule > ( " ContentBrowser " ) . Get ( ) ; ;
ContentBrowserSingleton . SaveContentBrowserSettings ( StatusBarContentBrowser ) ;
PreviousKeyboardFocusedWidget . Reset ( ) ;
}
void UStatusBarSubsystem : : HandleDeferredOpenContentBrowser ( TSharedPtr < SWindow > ParentWindow )
{
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
TSharedPtr < SDockTab > ParentTab = StatusBarPinned - > GetParentTab ( ) ;
if ( ParentTab & & ParentTab - > IsForeground ( ) & & ParentTab - > GetParentWindow ( ) = = ParentWindow )
{
StatusBarPinned - > OpenDrawer ( StatusBarDrawerIds : : ContentBrowser ) ;
break ;
}
}
}
}
TSharedRef < SWidget > UStatusBarSubsystem : : OnGetOutputLog ( )
{
if ( ! StatusBarOutputLog )
{
StatusBarOutputLog = FOutputLogModule : : Get ( ) . MakeOutputLogDrawerWidget ( FSimpleDelegate : : CreateUObject ( this , & UStatusBarSubsystem : : OnDebugConsoleDrawerClosed ) ) ;
}
return StatusBarOutputLog . ToSharedRef ( ) ;
}
void UStatusBarSubsystem : : OnOutputLogOpened ( FName StatusBarWithDrawerName )
{
// Dismiss any other content browser that is opened when one status bar opens it. The content browser is a shared resource and shouldn't be in the layout twice
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
if ( StatusBarWithDrawerName ! = StatusBarPinned - > GetStatusBarName ( ) | | StatusBarPinned - > IsAnyOtherDrawerOpened ( StatusBarDrawerIds : : OutputLog ) )
{
StatusBarPinned - > CloseDrawerImmediately ( ) ;
}
}
}
FOutputLogModule : : Get ( ) . FocusOutputLogConsoleBox ( StatusBarOutputLog . ToSharedRef ( ) ) ;
}
void UStatusBarSubsystem : : OnOutputLogDismised ( const TSharedPtr < SWidget > & NewlyFocusedWidget )
{
if ( PreviousKeyboardFocusedWidget . IsValid ( ) & & ! NewlyFocusedWidget . IsValid ( ) )
{
FSlateApplication : : Get ( ) . SetKeyboardFocus ( PreviousKeyboardFocusedWidget . Pin ( ) ) ;
}
PreviousKeyboardFocusedWidget . Reset ( ) ;
}
void UStatusBarSubsystem : : OnDebugConsoleDrawerClosed ( )
{
for ( auto StatusBar : StatusBars )
{
if ( TSharedPtr < SStatusBar > StatusBarPinned = StatusBar . Value . StatusBarWidget . Pin ( ) )
{
if ( StatusBarPinned - > IsDrawerOpened ( StatusBarDrawerIds : : OutputLog ) )
{
ToggleDebugConsole ( StatusBarPinned - > GetParentTab ( ) - > GetParentWindow ( ) . ToSharedRef ( ) ) ;
break ;
}
}
}
}
# undef LOCTEXT_NAMESPACE