2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "ContentBrowserPCH.h"
# include "CollectionViewTypes.h"
# include "CollectionContextMenu.h"
# include "ISourceControlModule.h"
# include "ContentBrowserModule.h"
2014-08-27 20:50:23 -04:00
# include "SColorPicker.h"
2014-10-14 22:50:06 -04:00
# include "GenericCommands.h"
2014-08-27 20:50:23 -04:00
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "ContentBrowser"
2014-08-27 20:50:23 -04:00
2014-03-14 14:13:41 -04:00
FCollectionContextMenu : : FCollectionContextMenu ( const TWeakPtr < SCollectionView > & InCollectionView )
: CollectionView ( InCollectionView )
, bProjectUnderSourceControl ( false )
{
}
void FCollectionContextMenu : : BindCommands ( TSharedPtr < FUICommandList > InCommandList )
{
InCommandList - > MapAction ( FGenericCommands : : Get ( ) . Rename , FUIAction (
FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecuteRenameCollection ) ,
FCanExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : CanExecuteRenameCollection )
) ) ;
}
TSharedPtr < SWidget > FCollectionContextMenu : : MakeCollectionListContextMenu ( TSharedPtr < FUICommandList > InCommandList )
{
// Get all menu extenders for this context menu from the content browser module
FContentBrowserModule & ContentBrowserModule = FModuleManager : : GetModuleChecked < FContentBrowserModule > ( TEXT ( " ContentBrowser " ) ) ;
TArray < FContentBrowserMenuExtender > MenuExtenderDelegates = ContentBrowserModule . GetAllCollectionListContextMenuExtenders ( ) ;
TArray < TSharedPtr < FExtender > > Extenders ;
for ( int32 i = 0 ; i < MenuExtenderDelegates . Num ( ) ; + + i )
{
if ( MenuExtenderDelegates [ i ] . IsBound ( ) )
{
Extenders . Add ( MenuExtenderDelegates [ i ] . Execute ( ) ) ;
}
}
TSharedPtr < FExtender > MenuExtender = FExtender : : Combine ( Extenders ) ;
FMenuBuilder MenuBuilder ( /*bInShouldCloseWindowAfterMenuSelection=*/ true , InCommandList , MenuExtender ) ;
UpdateProjectSourceControl ( ) ;
TArray < TSharedPtr < FCollectionItem > > CollectionList = CollectionView . Pin ( ) - > CollectionListPtr - > GetSelectedItems ( ) ;
MenuBuilder . BeginSection ( " CollectionOptions " , LOCTEXT ( " CollectionListOptionsMenuHeading " , " Collection Options " ) ) ;
{
// New... (submenu)
MenuBuilder . AddSubMenu (
LOCTEXT ( " NewCollection " , " New... " ) ,
LOCTEXT ( " NewCollectionTooltip " , " Create a collection. " ) ,
FNewMenuDelegate : : CreateRaw ( this , & FCollectionContextMenu : : MakeNewCollectionSubMenu )
) ;
// Only add rename/delete if at least one collection is selected
if ( CollectionList . Num ( ) )
{
bool bAnyManagedBySCC = false ;
for ( int32 CollectionIdx = 0 ; CollectionIdx < CollectionList . Num ( ) ; + + CollectionIdx )
{
if ( CollectionList [ CollectionIdx ] - > CollectionType ! = ECollectionShareType : : CST_Local )
{
bAnyManagedBySCC = true ;
break ;
}
}
if ( CollectionList . Num ( ) = = 1 )
{
// Rename
MenuBuilder . AddMenuEntry ( FGenericCommands : : Get ( ) . Rename , NAME_None , LOCTEXT ( " RenameCollection " , " Rename " ) , LOCTEXT ( " RenameCollectionTooltip " , " Rename this collection. " ) ) ;
}
// Delete
MenuBuilder . AddMenuEntry (
LOCTEXT ( " DestroyCollection " , " Delete " ) ,
LOCTEXT ( " DestroyCollectionTooltip " , " Delete this collection. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecuteDestroyCollection ) ,
FCanExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : CanExecuteDestroyCollection , bAnyManagedBySCC )
)
) ;
2014-04-23 18:13:40 -04:00
if ( CollectionList . Num ( ) = = 1 )
{
// If any colors have already been set, display color options as a sub menu
if ( CollectionViewUtils : : HasCustomColors ( ) )
{
// Set Color (submenu)
MenuBuilder . AddSubMenu (
LOCTEXT ( " SetColor " , " Set Color " ) ,
LOCTEXT ( " SetCollectionColorTooltip " , " Sets the color this collection should appear as. " ) ,
FNewMenuDelegate : : CreateRaw ( this , & FCollectionContextMenu : : MakeSetColorSubMenu )
) ;
}
else
{
// Set Color
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SetColor " , " Set Color " ) ,
LOCTEXT ( " SetCollectionColorTooltip " , " Sets the color this collection should appear as. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecutePickColor ) )
) ;
}
}
2014-03-14 14:13:41 -04:00
}
}
MenuBuilder . EndSection ( ) ;
return MenuBuilder . MakeWidget ( ) ;
}
void FCollectionContextMenu : : MakeNewCollectionSubMenu ( FMenuBuilder & MenuBuilder )
{
MenuBuilder . BeginSection ( " CollectionNewCollection " , LOCTEXT ( " NewCollectionMenuHeading " , " New Collection " ) ) ;
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " NewCollection_Shared " , " Shared Collection " ) ,
LOCTEXT ( " NewCollection_SharedTooltip " , " Create a collection that can be seen by anyone. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecuteNewCollection , ECollectionShareType : : CST_Shared ) ,
FCanExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : CanExecuteNewCollection , ECollectionShareType : : CST_Shared )
)
) ;
MenuBuilder . AddMenuEntry (
LOCTEXT ( " NewCollection_Private " , " Private Collection " ) ,
LOCTEXT ( " NewCollection_PrivateTooltip " , " Create a collection that can only be seen by you. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecuteNewCollection , ECollectionShareType : : CST_Private ) ,
FCanExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : CanExecuteNewCollection , ECollectionShareType : : CST_Private )
)
) ;
MenuBuilder . AddMenuEntry (
LOCTEXT ( " NewCollection_Local " , " Local Collection " ) ,
LOCTEXT ( " NewCollection_LocalTooltip " , " Create a collection that is not in source control and can only be seen by you. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecuteNewCollection , ECollectionShareType : : CST_Local ) ,
FCanExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : CanExecuteNewCollection , ECollectionShareType : : CST_Local )
)
) ;
}
MenuBuilder . EndSection ( ) ;
}
2014-04-23 18:13:40 -04:00
void FCollectionContextMenu : : MakeSetColorSubMenu ( FMenuBuilder & MenuBuilder )
{
// New Color
MenuBuilder . AddMenuEntry (
LOCTEXT ( " NewColor " , " New Color " ) ,
LOCTEXT ( " NewCollectionColorTooltip " , " Changes the color this collection should appear as. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecutePickColor ) )
) ;
// Clear Color (only required if any of the selection has one)
if ( SelectedHasCustomColors ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " ClearColor " , " Clear Color " ) ,
LOCTEXT ( " ClearCollectionColorTooltip " , " Resets the color this collection appears as. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FCollectionContextMenu : : ExecuteResetColor ) )
) ;
}
// Add all the custom colors the user has chosen so far
TArray < FLinearColor > CustomColors ;
if ( CollectionViewUtils : : HasCustomColors ( & CustomColors ) )
{
MenuBuilder . BeginSection ( " PathContextCustomColors " , LOCTEXT ( " CustomColorsExistingColors " , " Existing Colors " ) ) ;
{
for ( int32 ColorIndex = 0 ; ColorIndex < CustomColors . Num ( ) ; ColorIndex + + )
{
const FLinearColor & Color = CustomColors [ ColorIndex ] ;
MenuBuilder . AddWidget (
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 2 , 0 , 0 , 0 )
[
SNew ( SButton )
. ButtonStyle ( FEditorStyle : : Get ( ) , " Menu.Button " )
. OnClicked ( this , & FCollectionContextMenu : : OnColorClicked , Color )
[
SNew ( SColorBlock )
. Color ( Color )
. Size ( FVector2D ( 77 , 16 ) )
]
] ,
LOCTEXT ( " CustomColor " , " " ) ,
/*bNoIndent=*/ true
) ;
}
}
MenuBuilder . EndSection ( ) ;
}
}
2014-03-14 14:13:41 -04:00
void FCollectionContextMenu : : UpdateProjectSourceControl ( )
{
// Force update of source control so that we're always showing the valid options
bProjectUnderSourceControl = false ;
if ( ISourceControlModule : : Get ( ) . IsEnabled ( ) & & ISourceControlModule : : Get ( ) . GetProvider ( ) . IsAvailable ( ) & & FPaths : : IsProjectFilePathSet ( ) )
{
FSourceControlStatePtr SourceControlState = ISourceControlModule : : Get ( ) . GetProvider ( ) . GetState ( FPaths : : GetProjectFilePath ( ) , EStateCacheUsage : : ForceUpdate ) ;
bProjectUnderSourceControl = ( SourceControlState - > IsSourceControlled ( ) & & ! SourceControlState - > IsIgnored ( ) & & ! SourceControlState - > IsUnknown ( ) ) ;
}
}
2014-04-23 18:13:40 -04:00
bool FCollectionContextMenu : : CanRenameSelectedCollections ( ) const
{
TArray < TSharedPtr < FCollectionItem > > CollectionList = CollectionView . Pin ( ) - > CollectionListPtr - > GetSelectedItems ( ) ;
if ( CollectionList . Num ( ) = = 1 )
{
return ! ( CollectionList [ 0 ] - > CollectionType ! = ECollectionShareType : : CST_Local ) | | ( bProjectUnderSourceControl & & ISourceControlModule : : Get ( ) . IsEnabled ( ) & & ISourceControlModule : : Get ( ) . GetProvider ( ) . IsAvailable ( ) ) ;
}
return false ;
}
2014-03-14 14:13:41 -04:00
void FCollectionContextMenu : : ExecuteNewCollection ( ECollectionShareType : : Type CollectionType )
{
if ( ! ensure ( CollectionView . IsValid ( ) ) )
{
return ;
}
CollectionView . Pin ( ) - > CreateCollectionItem ( CollectionType ) ;
}
void FCollectionContextMenu : : ExecuteRenameCollection ( )
{
if ( ! ensure ( CollectionView . IsValid ( ) ) )
{
return ;
}
TArray < TSharedPtr < FCollectionItem > > CollectionList = CollectionView . Pin ( ) - > CollectionListPtr - > GetSelectedItems ( ) ;
if ( ! ensure ( CollectionList . Num ( ) = = 1 ) )
{
return ;
}
CollectionView . Pin ( ) - > RenameCollectionItem ( CollectionList [ 0 ] ) ;
}
void FCollectionContextMenu : : ExecuteDestroyCollection ( )
{
if ( ! ensure ( CollectionView . IsValid ( ) ) )
{
return ;
}
TArray < TSharedPtr < FCollectionItem > > CollectionList = CollectionView . Pin ( ) - > CollectionListPtr - > GetSelectedItems ( ) ;
FText Prompt ;
if ( CollectionList . Num ( ) = = 1 )
{
Prompt = FText : : Format ( LOCTEXT ( " CollectionDestroyConfirm_Single " , " Delete {0}? " ) , FText : : FromString ( CollectionList [ 0 ] - > CollectionName ) ) ;
}
else
{
Prompt = FText : : Format ( LOCTEXT ( " CollectionDestroyConfirm_Multiple " , " Delete {0} Collections? " ) , FText : : AsNumber ( CollectionList . Num ( ) ) ) ;
}
FOnClicked OnYesClicked = FOnClicked : : CreateSP ( this , & FCollectionContextMenu : : ExecuteDestroyCollectionConfirmed , CollectionList ) ;
ContentBrowserUtils : : DisplayConfirmationPopup (
Prompt ,
LOCTEXT ( " CollectionDestroyConfirm_Yes " , " Delete " ) ,
LOCTEXT ( " CollectionDestroyConfirm_No " , " Cancel " ) ,
CollectionView . Pin ( ) . ToSharedRef ( ) ,
OnYesClicked ) ;
}
FReply FCollectionContextMenu : : ExecuteDestroyCollectionConfirmed ( TArray < TSharedPtr < FCollectionItem > > CollectionList )
{
FCollectionManagerModule & CollectionManagerModule = FModuleManager : : Get ( ) . LoadModuleChecked < FCollectionManagerModule > ( TEXT ( " CollectionManager " ) ) ;
TArray < TSharedPtr < FCollectionItem > > ItemsToRemove ;
for ( int32 CollectionIdx = 0 ; CollectionIdx < CollectionList . Num ( ) ; + + CollectionIdx )
{
const TSharedPtr < FCollectionItem > & CollectionItem = CollectionList [ CollectionIdx ] ;
if ( CollectionManagerModule . Get ( ) . DestroyCollection ( FName ( * CollectionItem - > CollectionName ) , CollectionItem - > CollectionType ) )
{
// Refresh the list now that the collection has been removed
ItemsToRemove . Add ( CollectionItem ) ;
}
else
{
// Display a warning
const FVector2D & CursorPos = FSlateApplication : : Get ( ) . GetCursorPos ( ) ;
FSlateRect MessageAnchor ( CursorPos . X , CursorPos . Y , CursorPos . X , CursorPos . Y ) ;
ContentBrowserUtils : : DisplayMessage (
FText : : Format ( LOCTEXT ( " CollectionDestroyFailed " , " Failed to destroy collection. {0} " ) , CollectionManagerModule . Get ( ) . GetLastError ( ) ) ,
MessageAnchor ,
CollectionView . Pin ( ) - > CollectionListPtr . ToSharedRef ( )
) ;
}
}
if ( ItemsToRemove . Num ( ) > 0 )
{
CollectionView . Pin ( ) - > RemoveCollectionItems ( ItemsToRemove ) ;
}
return FReply : : Handled ( ) ;
}
2014-04-23 18:13:40 -04:00
void FCollectionContextMenu : : ExecuteResetColor ( )
{
ResetColors ( ) ;
}
void FCollectionContextMenu : : ExecutePickColor ( )
{
TSharedPtr < SCollectionView > CollectionViewPtr = CollectionView . Pin ( ) ;
TArray < FCollectionNameType > SelectedCollections = CollectionViewPtr - > GetSelectedCollections ( ) ;
// Spawn a color picker, so the user can select which color they want
TArray < FLinearColor * > LinearColorArray ;
FColorPickerArgs PickerArgs ;
PickerArgs . bIsModal = false ;
PickerArgs . ParentWidget = CollectionViewPtr ;
if ( SelectedCollections . Num ( ) > 0 )
{
// Make sure an color entry exists for all the collections, otherwise they won't update in realtime with the widget color
for ( int32 PathIdx = SelectedCollections . Num ( ) - 1 ; PathIdx > = 0 ; - - PathIdx )
{
const FCollectionNameType & SelectedCollection = SelectedCollections [ PathIdx ] ;
TSharedPtr < FLinearColor > Color = CollectionViewUtils : : LoadColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type ) ;
if ( ! Color . IsValid ( ) )
{
Color = MakeShareable ( new FLinearColor ( CollectionViewUtils : : GetDefaultColor ( ) ) ) ;
CollectionViewUtils : : SaveColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type , Color , true ) ;
}
else
{
// Default the color to the first valid entry
PickerArgs . InitialColorOverride = * Color . Get ( ) ;
}
LinearColorArray . Add ( Color . Get ( ) ) ;
}
PickerArgs . LinearColorArray = & LinearColorArray ;
}
PickerArgs . OnColorPickerWindowClosed = FOnWindowClosed : : CreateSP ( this , & FCollectionContextMenu : : NewColorComplete ) ;
OpenColorPicker ( PickerArgs ) ;
}
2014-03-14 14:13:41 -04:00
bool FCollectionContextMenu : : CanExecuteNewCollection ( ECollectionShareType : : Type CollectionType ) const
{
return ( CollectionType = = ECollectionShareType : : CST_Local ) | | ( bProjectUnderSourceControl & & ISourceControlModule : : Get ( ) . IsEnabled ( ) & & ISourceControlModule : : Get ( ) . GetProvider ( ) . IsAvailable ( ) ) ;
}
bool FCollectionContextMenu : : CanExecuteRenameCollection ( ) const
{
2014-04-23 18:13:40 -04:00
return CanRenameSelectedCollections ( ) ;
2014-03-14 14:13:41 -04:00
}
bool FCollectionContextMenu : : CanExecuteDestroyCollection ( bool bAnyManagedBySCC ) const
{
return ! bAnyManagedBySCC | | ( bProjectUnderSourceControl & & ISourceControlModule : : Get ( ) . IsEnabled ( ) & & ISourceControlModule : : Get ( ) . GetProvider ( ) . IsAvailable ( ) ) ;
}
2014-04-23 18:13:40 -04:00
bool FCollectionContextMenu : : SelectedHasCustomColors ( ) const
{
TSharedPtr < SCollectionView > CollectionViewPtr = CollectionView . Pin ( ) ;
TArray < FCollectionNameType > SelectedCollections = CollectionViewPtr - > GetSelectedCollections ( ) ;
for ( const FCollectionNameType & SelectedCollection : SelectedCollections )
{
// Ignore any that are the default color
const TSharedPtr < FLinearColor > Color = CollectionViewUtils : : LoadColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type ) ;
if ( Color . IsValid ( ) & & ! Color - > Equals ( CollectionViewUtils : : GetDefaultColor ( ) ) )
{
return true ;
}
}
return false ;
}
void FCollectionContextMenu : : NewColorComplete ( const TSharedRef < SWindow > & Window )
{
TSharedPtr < SCollectionView > CollectionViewPtr = CollectionView . Pin ( ) ;
TArray < FCollectionNameType > SelectedCollections = CollectionViewPtr - > GetSelectedCollections ( ) ;
// Save the colors back in the config (ptr should have already updated by the widget)
for ( const FCollectionNameType & SelectedCollection : SelectedCollections )
{
const TSharedPtr < FLinearColor > Color = CollectionViewUtils : : LoadColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type ) ;
check ( Color . IsValid ( ) ) ;
CollectionViewUtils : : SaveColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type , Color ) ;
}
}
FReply FCollectionContextMenu : : OnColorClicked ( const FLinearColor InColor )
{
TSharedPtr < SCollectionView > CollectionViewPtr = CollectionView . Pin ( ) ;
TArray < FCollectionNameType > SelectedCollections = CollectionViewPtr - > GetSelectedCollections ( ) ;
// Make sure an color entry exists for all the collections, otherwise it can't save correctly
for ( const FCollectionNameType & SelectedCollection : SelectedCollections )
{
TSharedPtr < FLinearColor > Color = CollectionViewUtils : : LoadColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type ) ;
if ( ! Color . IsValid ( ) )
{
Color = MakeShareable ( new FLinearColor ( ) ) ;
}
* Color . Get ( ) = InColor ;
CollectionViewUtils : : SaveColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type , Color ) ;
}
// Dismiss the menu here, as we can't make the 'clear' option appear if a folder has just had a color set for the first time
FSlateApplication : : Get ( ) . DismissAllMenus ( ) ;
return FReply : : Handled ( ) ;
}
void FCollectionContextMenu : : ResetColors ( )
{
TSharedPtr < SCollectionView > CollectionViewPtr = CollectionView . Pin ( ) ;
TArray < FCollectionNameType > SelectedCollections = CollectionViewPtr - > GetSelectedCollections ( ) ;
// Clear the custom colors for all the selected collections
for ( const FCollectionNameType & SelectedCollection : SelectedCollections )
{
CollectionViewUtils : : SaveColor ( SelectedCollection . Name . ToString ( ) , SelectedCollection . Type , nullptr ) ;
}
}
2014-03-14 14:13:41 -04:00
# undef LOCTEXT_NAMESPACE