2019-12-26 15:33:43 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
# include "SaveLayoutDialog.h"
2022-05-09 13:12:28 -04:00
# include "Styling/AppStyle.h"
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
# include "Framework/Application/SlateApplication.h"
# include "Interfaces/IMainFrameModule.h"
# include "Misc/FileHelper.h"
# include "Misc/MessageDialog.h"
# include "SlateOptMacros.h"
# include "Widgets/DeclarativeSyntaxSupport.h"
# include "Widgets/Input/SButton.h"
# include "Widgets/Input/SEditableTextBox.h"
# include "Widgets/Layout/SBox.h"
# include "Widgets/SBoxPanel.h"
# include "Widgets/SCompoundWidget.h"
# include "Widgets/Text/STextBlock.h"
2021-09-08 08:29:49 -04:00
# include "SPrimaryButton.h"
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
# define LOCTEXT_NAMESPACE "SaveLayoutDialog"
/**
* Note : Code for SSaveLayoutDialog obtained and modified from SAssetDialog
*
* A SWidget that generates a custom SCompoundWidget that allows the user to select the final file name where a layout ini file will be saved ,
* and optionally the displayed layout name and description .
*
* This SWidget is never meant to used by itself . Instead , FSaveLayoutDialogUtils : : CreateSaveLayoutAsDialogInStandaloneWindow ( ) should be called ,
* which additionally sets the right SWindow for SSaveLayoutDialog and blocks the thread until the user finishes interacting with it .
*/
class SSaveLayoutDialog : public SCompoundWidget
{
public :
SLATE_BEGIN_ARGS ( SSaveLayoutDialog ) { }
SLATE_END_ARGS ( )
SSaveLayoutDialog ( ) ;
virtual ~ SSaveLayoutDialog ( ) ;
virtual void Construct ( const FArguments & InArgs , const TSharedRef < FSaveLayoutDialogParams > & InSaveLayoutDialogParams ) ;
private :
FText GetFileNameText ( ) const ;
/** Gets the visibility of the name error label */
EVisibility GetNameErrorLabelVisibility ( ) const ;
/** Gets the text to display in the name error label */
FText GetNameErrorLabelText ( ) const ;
/** Fired when the layout name box text is committed */
void OnLayoutNameTextCommited ( const FText & InText , ETextCommit : : Type InCommitType ) ;
/** Fired when the layout description box text is committed */
void OnLayoutDescriptionTextCommited ( const FText & InText , ETextCommit : : Type InCommitType ) ;
/** Determines if the Save button is enabled. */
bool IsConfirmButtonEnabled ( ) const ;
/** Handler for when the Save button is clicked */
FReply OnConfirmClicked ( ) ;
/** Handler for when the cancel button is clicked */
FReply OnCancelClicked ( ) ;
/** Used to commit the object path used for saving in this dialog */
void CommitObjectPathForSave ( ) ;
/** Closes this dialog */
void CloseDialog ( ) ;
bool IsValidFilePathForCreation ( const FString & FilePath , const FString & FileName , FText & OutErrorMessage , bool bAllowExistingAsset = true ) const ;
void UpdateInputValidity ( ) ;
TSharedPtr < FSaveLayoutDialogParams > SaveLayoutDialogParams ;
FString DefaultDirectory ;
FString FinalFileName ;
FString FinalFilePath ;
FText CurrentlyEnteredLayoutName ;
FText CurrentlyEnteredLayoutDescription ;
/** The error text from the last validity check */
FText LastInputValidityErrorText ;
/** True if the last validity check returned that the class name/path is valid for creation */
bool bLastInputValidityCheckSuccessful ;
} ;
FSaveLayoutDialogParams : : FSaveLayoutDialogParams ( const FString & InDefaultDirectory , const FString & InFileExtension , const TArray < FText > & InLayoutNames , const TArray < FText > & InLayoutDescriptions )
: DefaultDirectory ( InDefaultDirectory )
, FileExtension ( InFileExtension )
, LayoutNames ( InLayoutNames )
, LayoutDescriptions ( InLayoutDescriptions )
{
}
void FSaveLayoutDialogUtils : : SanitizeText ( FString & InOutString )
{
// Replace any special character by `_`
for ( TCHAR & InOutChar : InOutString )
{
if ( ! FChar : : IsAlnum ( InOutChar ) )
{
InOutChar = ' _ ' ;
}
}
}
bool FSaveLayoutDialogUtils : : OverrideLayoutDialog ( const FString & LayoutIniFileName )
{
// Are you sure you want to do this?
const FText TextFileNameToRemove = FText : : FromString ( FPaths : : GetBaseFilename ( LayoutIniFileName ) ) ;
const FText TextBody = FText : : Format (
LOCTEXT ( " ActionOverrideLayoutMsg " , " Are you sure you want to permanently override the layout profile \" {0} \" with the current layout profile? This action cannot be undone. " ) , TextFileNameToRemove ) ;
const FText TextTitle = FText : : Format ( LOCTEXT ( " OverrideUILayout_Title " , " Override UI Layout \" {0} \" ? " ) , TextFileNameToRemove ) ;
return ( EAppReturnType : : Ok = = FMessageDialog : : Open ( EAppMsgType : : OkCancel , TextBody , & TextTitle ) ) ;
}
bool FSaveLayoutDialogUtils : : CreateSaveLayoutAsDialogInStandaloneWindow ( const TSharedRef < FSaveLayoutDialogParams > & InSaveLayoutDialogParams )
{
// Create SSaveLayoutDialog
TSharedRef < SSaveLayoutDialog > SaveLayoutDialog = SNew ( SSaveLayoutDialog , InSaveLayoutDialogParams ) ;
// Create SWindow that contains SSaveLayoutDialog
TSharedRef < SWindow > DialogWindow =
SNew ( SWindow )
. Title ( LOCTEXT ( " GenericAssetDialogWindowHeader " , " Save Layout As " ) )
2020-08-13 21:18:57 -04:00
. SizingRule ( ESizingRule : : Autosized ) ;
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
DialogWindow - > SetContent ( SaveLayoutDialog ) ;
// Launch SSaveLayoutDialog and block thread until user finishes with it
IMainFrameModule & MainFrameModule = FModuleManager : : LoadModuleChecked < IMainFrameModule > ( TEXT ( " MainFrame " ) ) ;
const TSharedPtr < SWindow > & MainFrameParentWindow = MainFrameModule . GetParentWindow ( ) ;
if ( MainFrameParentWindow . IsValid ( ) )
{
// Opposite to AddWindowAsNativeChild(), AddModalWindow() does not return until the modal window is closed
FSlateApplication : : Get ( ) . AddModalWindow ( DialogWindow , MainFrameParentWindow . ToSharedRef ( ) ) ;
return true ;
}
else
{
ensureMsgf ( false , TEXT ( " Could not create \" Save Layout As... \" dialog, this should never happen. " ) ) ;
return false ;
}
}
SSaveLayoutDialog : : SSaveLayoutDialog ( )
: bLastInputValidityCheckSuccessful ( false )
{
}
SSaveLayoutDialog : : ~ SSaveLayoutDialog ( )
{
}
void SSaveLayoutDialog : : Construct ( const FArguments & InArgs , const TSharedRef < FSaveLayoutDialogParams > & InSaveLayoutDialogParams )
{
SaveLayoutDialogParams = InSaveLayoutDialogParams ;
// Set Default Saving Directory
DefaultDirectory = SaveLayoutDialogParams - > DefaultDirectory ;
// Fill initial (default) values
if ( SaveLayoutDialogParams - > LayoutNames . Num ( ) > 0 )
{
ensureMsgf ( SaveLayoutDialogParams - > LayoutNames . Num ( ) = = 1 , TEXT ( " This code is only ready for SaveLayoutDialogParams->LayoutNames.Num() == 1. " ) ) ;
CurrentlyEnteredLayoutName = SaveLayoutDialogParams - > LayoutNames [ 0 ] ;
UpdateInputValidity ( ) ;
}
if ( SaveLayoutDialogParams - > LayoutDescriptions . Num ( ) > 0 )
{
ensureMsgf ( SaveLayoutDialogParams - > LayoutDescriptions . Num ( ) = = 1 , TEXT ( " This code is only ready for LayoutNames.Num() == 1. " ) ) ;
CurrentlyEnteredLayoutDescription = SaveLayoutDialogParams - > LayoutDescriptions [ 0 ] ;
}
// UI part
// The root SWidget in this dialog
TSharedRef < SVerticalBox > MainVerticalBox = SNew ( SVerticalBox ) ;
TSharedRef < SVerticalBox > ContentBox = SNew ( SVerticalBox ) ;
// Add to ChildSlot
ChildSlot
[
2020-08-13 21:18:57 -04:00
SNew ( SBorder )
2021-01-07 14:20:25 -04:00
. BorderImage ( FAppStyle : : Get ( ) . GetBrush ( " Brushes.Panel " ) )
2020-08-13 21:18:57 -04:00
[
SNew ( SBox )
. WidthOverride ( 600.f )
[
// Layout Name
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 5.0f , 2.0f )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
2020-08-18 15:08:46 -04:00
. FillWidth ( 0.6f )
2020-08-13 21:18:57 -04:00
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Center )
. Padding ( 5.0f , 2.0f )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " LayoutNameBoxLabel " , " Name " ) )
]
+ SHorizontalBox : : Slot ( )
. FillWidth ( 2.0f )
. VAlign ( VAlign_Center )
. Padding ( 5.0f , 2.0f )
[
SNew ( SEditableTextBox )
. Text ( CurrentlyEnteredLayoutName )
. OnTextCommitted ( this , & SSaveLayoutDialog : : OnLayoutNameTextCommited )
. OnTextChanged ( this , & SSaveLayoutDialog : : OnLayoutNameTextCommited , ETextCommit : : Default )
. SelectAllTextWhenFocused ( true )
]
]
+ SVerticalBox : : Slot ( )
. Padding ( 5.0f , 2.0f )
. AutoHeight ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
2020-08-18 15:08:46 -04:00
. FillWidth ( .6f )
2020-08-13 21:18:57 -04:00
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Center )
. Padding ( 5.0f , 2.0f )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " LayoutDescriptionBoxLabel " , " Description (Optional) " ) )
]
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
. FillWidth ( 2.0f )
. Padding ( 5.0f , 2.0f )
[
SNew ( SEditableTextBox )
. Text ( CurrentlyEnteredLayoutDescription )
. OnTextCommitted ( this , & SSaveLayoutDialog : : OnLayoutDescriptionTextCommited )
. OnTextChanged ( this , & SSaveLayoutDialog : : OnLayoutDescriptionTextCommited , ETextCommit : : Default )
. SelectAllTextWhenFocused ( true )
]
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
// Constant height, whether the label is visible or not
SNew ( SBox )
. HeightOverride ( 20 )
[
SNew ( SBorder )
. Visibility ( this , & SSaveLayoutDialog : : GetNameErrorLabelVisibility )
2022-05-09 13:12:28 -04:00
. BorderImage ( FAppStyle : : GetBrush ( " AssetDialog.ErrorLabelBorder " ) )
2020-08-13 21:18:57 -04:00
. Content ( )
[
SNew ( STextBlock )
. Text ( this , & SSaveLayoutDialog : : GetNameErrorLabelText )
. ToolTipText ( this , & SSaveLayoutDialog : : GetNameErrorLabelText )
]
]
]
+ SVerticalBox : : Slot ( )
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Bottom )
. Padding ( 0 , 0 , 5 , 5 )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Bottom )
. Padding ( 4 , 3 )
[
2021-09-08 08:29:49 -04:00
SNew ( SPrimaryButton )
2020-08-13 21:18:57 -04:00
. Text ( LOCTEXT ( " SaveLayoutDialogSaveButton " , " Save " ) )
. IsEnabled ( this , & SSaveLayoutDialog : : IsConfirmButtonEnabled )
. OnClicked ( this , & SSaveLayoutDialog : : OnConfirmClicked )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Bottom )
. Padding ( 4 , 3 )
[
SNew ( SButton )
. Text ( LOCTEXT ( " SaveLayoutDialogCancelButton " , " Cancel " ) )
. OnClicked ( this , & SSaveLayoutDialog : : OnCancelClicked )
]
]
]
]
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
] ;
}
FText SSaveLayoutDialog : : GetFileNameText ( ) const
{
return FText : : FromString ( FinalFileName ) ;
}
EVisibility SSaveLayoutDialog : : GetNameErrorLabelVisibility ( ) const
{
return GetNameErrorLabelText ( ) . IsEmpty ( ) ? EVisibility : : Hidden : EVisibility : : Visible ;
}
FText SSaveLayoutDialog : : GetNameErrorLabelText ( ) const
{
if ( ! bLastInputValidityCheckSuccessful )
{
return LastInputValidityErrorText ;
}
return FText : : GetEmpty ( ) ;
}
void SSaveLayoutDialog : : OnLayoutNameTextCommited ( const FText & InText , ETextCommit : : Type InCommitType )
{
CurrentlyEnteredLayoutName = InText ;
UpdateInputValidity ( ) ;
if ( InCommitType = = ETextCommit : : OnEnter )
{
CommitObjectPathForSave ( ) ;
}
}
void SSaveLayoutDialog : : OnLayoutDescriptionTextCommited ( const FText & InText , ETextCommit : : Type InCommitType )
{
CurrentlyEnteredLayoutDescription = InText ;
if ( InCommitType = = ETextCommit : : OnEnter )
{
CommitObjectPathForSave ( ) ;
}
}
bool SSaveLayoutDialog : : IsConfirmButtonEnabled ( ) const
{
return bLastInputValidityCheckSuccessful ;
}
FReply SSaveLayoutDialog : : OnConfirmClicked ( )
{
CommitObjectPathForSave ( ) ;
return FReply : : Handled ( ) ;
}
FReply SSaveLayoutDialog : : OnCancelClicked ( )
{
bLastInputValidityCheckSuccessful = false ;
2021-10-12 21:21:22 -04:00
if ( SaveLayoutDialogParams . IsValid ( ) )
{
SaveLayoutDialogParams - > bWereFilesSelected = false ;
SaveLayoutDialogParams - > LayoutFilePaths . Empty ( ) ;
SaveLayoutDialogParams - > LayoutNames . Empty ( ) ;
SaveLayoutDialogParams - > LayoutDescriptions . Empty ( ) ;
}
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
CloseDialog ( ) ;
return FReply : : Handled ( ) ;
}
void SSaveLayoutDialog : : CommitObjectPathForSave ( )
{
// Update final values and close dialog if valid input and not duplicated
if ( bLastInputValidityCheckSuccessful )
{
// Sanity check
if ( SaveLayoutDialogParams . IsValid ( ) )
{
// Are you sure you want to do this?
if ( FPaths : : FileExists ( FinalFilePath ) & & ! FSaveLayoutDialogUtils : : OverrideLayoutDialog ( FinalFilePath ) )
{
return ;
}
// Update output parameters
SaveLayoutDialogParams - > bWereFilesSelected = bLastInputValidityCheckSuccessful ;
SaveLayoutDialogParams - > LayoutFilePaths . Empty ( ) ;
SaveLayoutDialogParams - > LayoutNames . Empty ( ) ;
SaveLayoutDialogParams - > LayoutDescriptions . Empty ( ) ;
if ( SaveLayoutDialogParams - > bWereFilesSelected )
{
SaveLayoutDialogParams - > LayoutFilePaths . Emplace ( FinalFilePath ) ;
SaveLayoutDialogParams - > LayoutNames . Emplace ( CurrentlyEnteredLayoutName ) ;
SaveLayoutDialogParams - > LayoutDescriptions . Emplace ( CurrentlyEnteredLayoutDescription ) ;
}
}
else
{
ensureMsgf ( false , TEXT ( " SaveLayoutDialogParams should never be a nullptr at this point, it is ideally initialized in the Construct() class. " ) ) ;
}
// Close dialog
CloseDialog ( ) ;
}
}
void SSaveLayoutDialog : : CloseDialog ( )
{
TSharedPtr < SWindow > ContainingWindow = FSlateApplication : : Get ( ) . FindWidgetWindow ( AsShared ( ) ) ;
if ( ContainingWindow . IsValid ( ) )
{
ContainingWindow - > RequestDestroyWindow ( ) ;
}
}
bool SSaveLayoutDialog : : IsValidFilePathForCreation ( const FString & FilePath , const FString & FileName , FText & OutErrorMessage , bool bAllowExistingAsset ) const
{
// Make sure the name is not already a class or otherwise invalid for saving
if ( ! FFileHelper : : IsFilenameValidForSaving ( FileName , OutErrorMessage ) )
{
// Return false to indicate that the user should enter a new name
return false ;
}
// Make sure the new name only contains valid characters
if ( ! FName : : IsValidXName ( FileName , INVALID_OBJECTNAME_CHARACTERS INVALID_LONGPACKAGE_CHARACTERS , & OutErrorMessage ) )
{
// Return false to indicate that the user should enter a new name
return false ;
}
// Make sure we are not creating an FName that is too large
2019-11-12 18:10:20 -05:00
if ( FilePath . Len ( ) > = NAME_SIZE )
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
{
// This asset already exists at this location, inform the user and continue
2019-11-12 18:10:20 -05:00
OutErrorMessage = FText : : Format ( LOCTEXT ( " SaveLayoutNameTooLong " , " This layout file name is too long ({0} characters), the maximum is {1}. Please choose a shorter name. File name: {2} " ) ,
FText : : AsNumber ( FilePath . Len ( ) ) , FText : : AsNumber ( NAME_SIZE - 1 ) , FText : : FromString ( FilePath ) ) ;
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
// Return false to indicate that the user should enter a new name
return false ;
}
// Make sure we are not creating an path that is too long for the OS
const FString FullPath = FPaths : : ConvertRelativePathToFull ( FilePath ) ;
2019-11-12 18:10:20 -05:00
if ( FullPath . Len ( ) > = FPlatformMisc : : GetMaxPathLength ( ) )
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
{
// The full path for the asset is too long
2020-10-22 19:19:16 -04:00
OutErrorMessage = FText : : Format ( LOCTEXT ( " SaveLayoutFullPathTooLong " , " The full path for the asset is too long ({0} characters), the maximum is {1}. Please choose a shorter name or create it in a shallower folder structure. Full path: {2} " ) ,
2019-11-12 18:10:20 -05:00
FText : : AsNumber ( FullPath . Len ( ) ) , FText : : AsNumber ( FPlatformMisc : : GetMaxPathLength ( ) - 1 ) , FText : : FromString ( FullPath ) ) ;
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
// Return false to indicate that the user should enter a new name
return false ;
}
// Check for an existing asset, unless it we were asked not to.
if ( ! bAllowExistingAsset )
{
if ( FPaths : : FileExists ( FilePath ) )
{
// This asset already exists at this location, inform the user and continue
2019-11-12 18:10:20 -05:00
OutErrorMessage = FText : : Format ( LOCTEXT ( " SaveLayoutAlreadyExists " , " An asset already exists at this location with the name '{0}'. " ) , FText : : FromString ( FileName ) ) ;
Copied CL# 10088684
#jira UE-80569
#jira UE-80575
#jira UE-80577
New features (they are very related to each other, so they have been integrated together):
1) UE-80569: When the user attempts to save a custom layout, we open a Slate SWidget save dialog that no longer allows them to enter the file path where the layout will be saved, but instead the Layout Name and (optionally) Description. The file name will automatically be generated from the displayed layout name.
2) UE-80575: When attempting to save a custom layout, we prevent the OS save dialog. Since the user cannot actually save a layout anywhere other than the default save location, this streamlines the workflow and minimize confusion. Instead, the Slate SWidget detailed in point 1 is used, where the user can introduce only the displayed layout name, and the file name and its directory are automatically generated (fixed directory).
3) UE-80577: After 1 and 2, it is unclear where the layout is saved. Thus, when saving a custom layout, we provide an Editor toast notifying the user of their custom layout's save location. It is analog to the one provided when a user takes a screenshot within the Editor.
In addition, the possible messages displayed to the user when the layout file was not successfully copied have also been improved (higher details and fixed some grammar typos).
Some general and additional considerations about the new Slate layout save dialog:
1) The "Save" button will be disabled when the introduced file name is empty or an error occurs (e.g., name is too long). If any error occurs, the dialog will display the error message as well, analog to "File" --> "Save current as...".
2) An Override/Cancel dialog will be displayed if the user selects a file name that matches another existing one.
3) An automatic NSLOCTEXT key and namespace fields are generated for each profile created. This is abstracted from the user, who does not need to know about this. Translations come later from a LocRes file that we generate for the engine. Thus, only the profile files that we have included in P4 might be translated.
Some potential issues / observations:
1) The export layout remains with the old OS save dialog (as it can be saved in different directories). This makes the appearance of both of them very different, but it also makes export similar to import.
#rb rex.hill
#ROBOMERGE-SOURCE: CL 10089258 in //UE4/Release-4.24/...
#ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v574-10069753)
[CL 10089279 by gines hidalgo in Main branch]
2019-11-08 17:44:25 -05:00
// Return false to indicate that the user should enter a new name
return false ;
}
}
return true ;
}
void SSaveLayoutDialog : : UpdateInputValidity ( )
{
// Update file name
FinalFileName = CurrentlyEnteredLayoutName . ToString ( ) ;
FSaveLayoutDialogUtils : : SanitizeText ( FinalFileName ) ;
// Fill full layout file path from file name and directory
FinalFilePath =
// Folder
( DefaultDirectory . Right ( 1 ) = = TEXT ( " / " ) ? DefaultDirectory : DefaultDirectory + TEXT ( " / " ) )
// FileName + Extension
+ ( FinalFileName . Len ( ) > SaveLayoutDialogParams - > FileExtension . Len ( ) & & FinalFileName . Right ( 3 ) = = SaveLayoutDialogParams - > FileExtension
? FinalFileName : FinalFileName + SaveLayoutDialogParams - > FileExtension ) ;
// Validate file name
bLastInputValidityCheckSuccessful = true ;
// No error text for an empty name. Just fail validity.
if ( FinalFileName . IsEmpty ( ) )
{
bLastInputValidityCheckSuccessful = false ;
LastInputValidityErrorText = FText : : GetEmpty ( ) ;
}
if ( bLastInputValidityCheckSuccessful )
{
FText ErrorMessage ;
if ( ! IsValidFilePathForCreation ( FinalFilePath , FinalFileName , ErrorMessage ) )
{
bLastInputValidityCheckSuccessful = false ;
LastInputValidityErrorText = ErrorMessage ;
}
}
}
# undef LOCTEXT_NAMESPACE