// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. #include "AutomationWindowPrivatePCH.h" #include "AutomationController.h" #include "AutomationPresetManager.h" #include "SAutomationWindow.h" #include "SSearchBox.h" #include "SNotificationList.h" #include "SThrobber.h" #define LOCTEXT_NAMESPACE "AutomationTest" ////////////////////////////////////////////////////////////////////////// // FAutomationWindowCommands class FAutomationWindowCommands : public TCommands { public: FAutomationWindowCommands() : TCommands( TEXT("AutomationWindow"), NSLOCTEXT("Contexts", "AutomationWindow", "Automation Window"), NAME_None, FEditorStyle::GetStyleSetName() ) { } virtual void RegisterCommands() override { UI_COMMAND( RefreshTests, "Refresh Tests", "Refresh Tests", EUserInterfaceActionType::Button, FInputChord() ); UI_COMMAND( FindWorkers, "Find Workers", "Find Workers", EUserInterfaceActionType::Button, FInputChord() ); UI_COMMAND( ErrorFilter, "Errors", "Toggle Error Filter", EUserInterfaceActionType::ToggleButton, FInputChord() ); UI_COMMAND( WarningFilter, "Warnings", "Toggle Warning Filter", EUserInterfaceActionType::ToggleButton, FInputChord() ); UI_COMMAND( SmokeTestFilter, "Smoke Tests", "Toggle Smoke Test Filter", EUserInterfaceActionType::ToggleButton, FInputChord() ); UI_COMMAND( DeveloperDirectoryContent, "Dev Content", "Developer Directory Content Filter (when enabled, developer directories are also included)", EUserInterfaceActionType::ToggleButton, FInputChord() ); UI_COMMAND( VisualCommandlet, "Vis Cmdlet", "Visual Commandlet Filter", EUserInterfaceActionType::ToggleButton, FInputChord() ); } public: TSharedPtr RefreshTests; TSharedPtr FindWorkers; TSharedPtr ErrorFilter; TSharedPtr WarningFilter; TSharedPtr SmokeTestFilter; TSharedPtr DeveloperDirectoryContent; TSharedPtr VisualCommandlet; }; ////////////////////////////////////////////////////////////////////////// // SAutomationWindow SAutomationWindow::SAutomationWindow() : ColumnWidth(50.0f) { } SAutomationWindow::~SAutomationWindow() { // @todo PeterMcW: is there an actual delegate missing here? //give the controller a way to indicate it requires a UI update //AutomationController->SetRefreshTestCallback(FOnAutomationControllerTestsRefreshed()); // Remove ourselves from the session manager if( SessionManager.IsValid( ) ) { SessionManager->OnCanSelectSession().RemoveAll(this); SessionManager->OnSelectedSessionChanged().RemoveAll(this); SessionManager->OnSessionInstanceUpdated().RemoveAll(this); } if (AutomationController.IsValid()) { AutomationController->RemoveCallbacks(); } } BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SAutomationWindow::Construct( const FArguments& InArgs, const IAutomationControllerManagerRef& InAutomationController, const ISessionManagerRef& InSessionManager ) { FAutomationWindowCommands::Register(); CreateCommands(); TestPresetManager = MakeShareable(new FAutomationTestPresetManager()); TestPresetManager->LoadPresets(); bAddingTestPreset = false; bHasChildTestSelected = false; SessionManager = InSessionManager; AutomationController = InAutomationController; AutomationController->OnTestsRefreshed().BindRaw(this, &SAutomationWindow::OnRefreshTestCallback); AutomationController->OnTestsAvailable().BindRaw(this, &SAutomationWindow::OnTestAvailableCallback); AutomationControllerState = AutomationController->GetTestState(); //cache off reference to filtered reports TArray >& TestReports = AutomationController->GetReports(); // Create the search filter and set criteria AutomationTextFilter = MakeShareable( new AutomationReportTextFilter( AutomationReportTextFilter::FItemToStringArray::CreateSP( this, &SAutomationWindow::PopulateReportSearchStrings ) ) ); AutomationGeneralFilter = MakeShareable( new FAutomationFilter() ); AutomationFilters = MakeShareable( new AutomationFilterCollection() ); AutomationFilters->Add( AutomationTextFilter ); AutomationFilters->Add( AutomationGeneralFilter ); bIsRequestingTests = false; // Test history tracking bIsTrackingHistory = AutomationController->IsTrackingHistory(); NumHistoryElementsToTrack = AutomationController->GetNumberHistoryItemsTracking(); //make the widget for platforms PlatformsHBox = SNew (SHorizontalBox); TestTable = SNew(SAutomationTestTreeView< TSharedPtr< IAutomationReport > >) .SelectionMode(ESelectionMode::Multi) .TreeItemsSource( &TestReports ) // Generates the actual widget for a tree item .OnGenerateRow( this, &SAutomationWindow::OnGenerateWidgetForTest ) // Gets children .OnGetChildren(this, &SAutomationWindow::OnGetChildren) //on selection .OnSelectionChanged(this, &SAutomationWindow::OnTestSelectionChanged) // Allow for some spacing between items with a larger item height. .ItemHeight(20.0f) #if WITH_EDITOR // If in editor - add a context menu for opening assets when in editor .OnContextMenuOpening(this, &SAutomationWindow::HandleAutomationListContextMenuOpening) #endif .HeaderRow ( SAssignNew(TestTableHeaderRow,SHeaderRow) + SHeaderRow::Column( AutomationTestWindowConstants::Title ) .FillWidth(300.0f) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .AutoWidth() .HAlign(HAlign_Center) [ //global enable/disable check box SAssignNew(HeaderCheckbox, SCheckBox) .OnCheckStateChanged( this, &SAutomationWindow::HeaderCheckboxStateChange) .ToolTipText( LOCTEXT( "Enable Disable Test", "Enable / Disable Test" ) ) ] +SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) [ SNew( STextBlock ) .Text( LOCTEXT("TestName_Header", "Test Name") ) ] ] + SHeaderRow::Column( AutomationTestWindowConstants::SmokeTest ) .HAlignHeader(HAlign_Center) .VAlignHeader(VAlign_Center) .HAlignCell(HAlign_Center) .VAlignCell(VAlign_Center) .FixedWidth( 50.0f ) [ //icon for the smoke test column SNew(SImage) .ColorAndOpacity(FLinearColor(1.0f, 1.0f, 1.0f, 0.4f)) .ToolTipText( LOCTEXT( "Smoke Test", "Smoke Test" ) ) .Image(FEditorStyle::GetBrush("Automation.SmokeTest")) ] + SHeaderRow::Column( AutomationTestWindowConstants::RequiredDeviceCount ) .HAlignHeader(HAlign_Center) .VAlignHeader(VAlign_Center) .HAlignCell(HAlign_Center) .VAlignCell(VAlign_Center) .FixedWidth( 50.0f ) [ SNew( SImage ) .Image( FEditorStyle::GetBrush("Automation.ParticipantsWarning") ) .ToolTipText( LOCTEXT( "RequiredDeviceCountWarningToolTip", "Number of devices required." ) ) ] + SHeaderRow::Column( AutomationTestWindowConstants::Status ) .FillWidth(650.0f) [ //platform header placeholder PlatformsHBox.ToSharedRef() ] + SHeaderRow::Column( AutomationTestWindowConstants::Timing ) .FillWidth(150.0f) .DefaultLabel( LOCTEXT("TestDurationRange", "Duration") ) ); if(bIsTrackingHistory) { TestTableHeaderRow->AddColumn( SHeaderRow::Column(AutomationTestWindowConstants::History) .HAlignHeader(HAlign_Center) .VAlignHeader(VAlign_Center) .HAlignCell(HAlign_Center) .VAlignCell(VAlign_Center) .FixedWidth(100.0f) .DefaultLabel(LOCTEXT("TestHistory", "Test History")) ); } TSharedRef NotificationList = SNew(SNotificationList) .Visibility( EVisibility::HitTestInvisible ); //build the actual guts of the window this->ChildSlot [ SNew(SOverlay) + SOverlay::Slot() [ SNew( SSplitter ) .Orientation(Orient_Vertical) +SSplitter::Slot() .Value(0.66f) [ //automation test panel SAssignNew( MenuBar, SVerticalBox ) //ACTIONS +SVerticalBox::Slot() .AutoHeight() [ SNew( SHorizontalBox ) +SHorizontalBox::Slot() .AutoWidth() .HAlign(HAlign_Left) .VAlign(VAlign_Center) [ SAutomationWindow::MakeAutomationWindowToolBar( AutomationWindowActions.ToSharedRef(), SharedThis(this) ) ] ] +SVerticalBox::Slot() .FillHeight(1.0f) .Padding(0.0f, 8.0f, 0.0f, 0.0f) [ SNew(SOverlay) +SOverlay::Slot() [ SNew(SBorder) .BorderImage(this, &SAutomationWindow::GetTestBackgroundBorderImage) .Padding(3.0f) [ //the actual table full of tests TestTable.ToSharedRef() ] ] +SOverlay::Slot() .HAlign(HAlign_Center) .VAlign(VAlign_Center) [ SNew(SThrobber) .Visibility(this, &SAutomationWindow::GetTestsUpdatingThrobberVisibility) ] ] ] +SSplitter::Slot() .Value(0.33f) [ SNew(SOverlay) +SOverlay::Slot() [ SNew(SBox) .Visibility(this, &SAutomationWindow::GetTestGraphVisibility) [ //Graphical Results Panel SNew( SVerticalBox ) +SVerticalBox::Slot() .AutoHeight() [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .HAlign(HAlign_Left) [ SNew(STextBlock) .Text( LOCTEXT("AutomationTest_GraphicalResults", "Automation Test Graphical Results:")) ] +SHorizontalBox::Slot() .HAlign(HAlign_Right) .AutoWidth() [ SNew(STextBlock) .Text( LOCTEXT("AutomationTest_Display", "Display:")) ] +SHorizontalBox::Slot() .HAlign(HAlign_Right) .AutoWidth() [ SNew(SCheckBox) .Style(FCoreStyle::Get(), "RadioButton") .IsChecked(this, &SAutomationWindow::HandleResultDisplayTypeIsChecked, EAutomationGrapicalDisplayType::DisplayName) .OnCheckStateChanged(this, &SAutomationWindow::HandleResultDisplayTypeStateChanged, EAutomationGrapicalDisplayType::DisplayName) [ SNew(STextBlock) .Text( LOCTEXT("AutomationTest_GraphicalResultsDisplayName", "Name")) ] ] +SHorizontalBox::Slot() .HAlign(HAlign_Right) .AutoWidth() [ SNew(SCheckBox) .Style(FCoreStyle::Get(), "RadioButton") .IsChecked(this, &SAutomationWindow::HandleResultDisplayTypeIsChecked, EAutomationGrapicalDisplayType::DisplayTime) .OnCheckStateChanged(this, &SAutomationWindow::HandleResultDisplayTypeStateChanged, EAutomationGrapicalDisplayType::DisplayTime) [ SNew(STextBlock) .Text( LOCTEXT("AutomationTest_GraphicalResultsDisplayTime", "Time")) ] ] ] +SVerticalBox::Slot() .FillHeight(1.0f) [ SNew(SBorder) [ SNew(SScrollBox) + SScrollBox::Slot() [ SAssignNew(GraphicalResultBox, SAutomationGraphicalResultBox, InAutomationController) ] ] ] ] ] +SOverlay::Slot() [ SNew(SBox) .Visibility(this, &SAutomationWindow::GetTestLogVisibility) [ //results panel SNew( SVerticalBox ) +SVerticalBox::Slot() .AutoHeight() [ SNew( STextBlock ) .Text( LOCTEXT("AutomationTest_Results", "Automation Test Results:") ) ] +SVerticalBox::Slot() .FillHeight(1.0f) .Padding(0.0f, 4.0f, 0.0f, 0.0f) [ //list of results for the selected test SNew(SBorder) [ SAssignNew(LogListView, SListView >) .ItemHeight(18) .ListItemsSource(&LogMessages) .SelectionMode(ESelectionMode::Multi) .OnGenerateRow(this, &SAutomationWindow::OnGenerateWidgetForLog) .OnSelectionChanged(this, &SAutomationWindow::HandleLogListSelectionChanged) ] ] +SVerticalBox::Slot() .AutoHeight() .Padding(0.0f, 4.0f, 0.0f, 0.0f) [ SNew(SBorder) .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) .Padding(FMargin(8.0f, 6.0f)) [ // Add the command bar SAssignNew(CommandBar, SAutomationWindowCommandBar, NotificationList) .OnCopyLogClicked(this, &SAutomationWindow::HandleCommandBarCopyLogClicked) ] ] ] ] ] ] + SOverlay::Slot() .HAlign( HAlign_Center ) .VAlign( VAlign_Center ) .Padding( 15.0f ) [ NotificationList ] + SOverlay::Slot() .HAlign( HAlign_Center ) .VAlign( VAlign_Center ) .Padding( 15.0f ) [ SNew(SBorder) .BorderImage(FEditorStyle::GetBrush("NotificationList.ItemBackground")) .Padding(8.0f) .Visibility(this, &SAutomationWindow::HandleSelectSessionOverlayVisibility) [ SNew(STextBlock) .Text(LOCTEXT("SelectSessionOverlayText", "Please select a session from the Session Browser")) ] ] ]; SessionManager->OnCanSelectSession().AddSP( this, &SAutomationWindow::HandleSessionManagerCanSelectSession ); SessionManager->OnSelectedSessionChanged().AddSP( this, &SAutomationWindow::HandleSessionManagerSelectionChanged ); SessionManager->OnSessionInstanceUpdated().AddSP( this, &SAutomationWindow::HandleSessionManagerInstanceChanged ); FindWorkers(); } END_SLATE_FUNCTION_BUILD_OPTIMIZATION void SAutomationWindow::HandleResultDisplayTypeStateChanged( ECheckBoxState NewRadioState, EAutomationGrapicalDisplayType::Type NewDisplayType) { if (NewRadioState == ECheckBoxState::Checked) { GraphicalResultBox->SetDisplayType(NewDisplayType); } } ECheckBoxState SAutomationWindow::HandleResultDisplayTypeIsChecked( EAutomationGrapicalDisplayType::Type InDisplayType ) const { return (GraphicalResultBox->GetDisplayType() == InDisplayType) ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; } const FSlateBrush* SAutomationWindow::GetTestBackgroundBorderImage() const { switch(TestBackgroundType) { case EAutomationTestBackgroundStyle::Game: return FEditorStyle::GetBrush("AutomationWindow.GameGroupBorder"); case EAutomationTestBackgroundStyle::Editor: return FEditorStyle::GetBrush("AutomationWindow.EditorGroupBorder"); case EAutomationTestBackgroundStyle::Unknown: default: return FEditorStyle::GetBrush("ToolPanel.GroupBorder"); } } void SAutomationWindow::CreateCommands() { check(!AutomationWindowActions.IsValid()); AutomationWindowActions = MakeShareable(new FUICommandList); const FAutomationWindowCommands& Commands = FAutomationWindowCommands::Get(); FUICommandList& ActionList = *AutomationWindowActions; ActionList.MapAction( Commands.RefreshTests, FExecuteAction::CreateRaw( this, &SAutomationWindow::ListTests ), FCanExecuteAction::CreateRaw( this, &SAutomationWindow::IsAutomationControllerIdle ) ); ActionList.MapAction( Commands.FindWorkers, FExecuteAction::CreateRaw( this, &SAutomationWindow::FindWorkers ), FCanExecuteAction::CreateRaw( this, &SAutomationWindow::IsAutomationControllerIdle ) ); ActionList.MapAction( Commands.ErrorFilter, FExecuteAction::CreateRaw( this, &SAutomationWindow::OnToggleErrorFilter ), FCanExecuteAction::CreateRaw( this, &SAutomationWindow::IsAutomationControllerIdle ), FIsActionChecked::CreateRaw( this, &SAutomationWindow::IsErrorFilterOn ) ); ActionList.MapAction( Commands.WarningFilter, FExecuteAction::CreateRaw( this, &SAutomationWindow::OnToggleWarningFilter ), FCanExecuteAction::CreateRaw( this, &SAutomationWindow::IsAutomationControllerIdle ), FIsActionChecked::CreateRaw( this, &SAutomationWindow::IsWarningFilterOn ) ); ActionList.MapAction( Commands.SmokeTestFilter, FExecuteAction::CreateRaw( this, &SAutomationWindow::OnToggleSmokeTestFilter ), FCanExecuteAction::CreateRaw( this, &SAutomationWindow::IsAutomationControllerIdle ), FIsActionChecked::CreateRaw( this, &SAutomationWindow::IsSmokeTestFilterOn ) ); ActionList.MapAction( Commands.DeveloperDirectoryContent, FExecuteAction::CreateRaw( this, &SAutomationWindow::OnToggleDeveloperDirectoryIncluded ), FCanExecuteAction::CreateRaw( this, &SAutomationWindow::IsAutomationControllerIdle ), FIsActionChecked::CreateRaw( this, &SAutomationWindow::IsDeveloperDirectoryIncluded ) ); ActionList.MapAction( Commands.VisualCommandlet, FExecuteAction::CreateRaw( this, &SAutomationWindow::OnToggleVisualCommandletFilter ), FCanExecuteAction::CreateRaw( this, &SAutomationWindow::IsAutomationControllerIdle ), FIsActionChecked::CreateRaw( this, &SAutomationWindow::IsVisualCommandletFilterOn ) ); } TSharedRef< SWidget > SAutomationWindow::MakeAutomationWindowToolBar( const TSharedRef& InCommandList, TSharedPtr InAutomationWindow ) { return InAutomationWindow->MakeAutomationWindowToolBar(InCommandList); } BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION TSharedRef< SWidget > SAutomationWindow::MakeAutomationWindowToolBar( const TSharedRef& InCommandList ) { struct Local { static void FillToolbar(FToolBarBuilder& ToolbarBuilder, TSharedRef RunTests, TSharedRef Searchbox, TSharedRef PresetBox, TSharedRef HistoryBox, TWeakPtr InAutomationWindow) { ToolbarBuilder.BeginSection("Automation"); { ToolbarBuilder.AddWidget( RunTests ); FUIAction DefaultAction; ToolbarBuilder.AddComboButton( DefaultAction, FOnGetContent::CreateStatic( &SAutomationWindow::GenerateTestsOptionsMenuContent, InAutomationWindow ), LOCTEXT( "TestOptions_Label", "Test Options" ), LOCTEXT( "TestOptionsToolTip", "Test Options" ), FSlateIcon(FEditorStyle::GetStyleSetName(), "AutomationWindow.TestOptions"), true); ToolbarBuilder.AddToolBarButton( FAutomationWindowCommands::Get().RefreshTests ); ToolbarBuilder.AddToolBarButton( FAutomationWindowCommands::Get().FindWorkers ); } ToolbarBuilder.EndSection(); ToolbarBuilder.BeginSection("Filters"); { ToolbarBuilder.AddToolBarButton( FAutomationWindowCommands::Get().ErrorFilter ); ToolbarBuilder.AddToolBarButton( FAutomationWindowCommands::Get().WarningFilter ); ToolbarBuilder.AddToolBarButton( FAutomationWindowCommands::Get().SmokeTestFilter ); ToolbarBuilder.AddToolBarButton( FAutomationWindowCommands::Get().DeveloperDirectoryContent ); ToolbarBuilder.AddToolBarButton( FAutomationWindowCommands::Get().VisualCommandlet ); } ToolbarBuilder.EndSection(); ToolbarBuilder.BeginSection("GroupFlags"); { ToolbarBuilder.AddComboButton( FUIAction(), FOnGetContent::CreateStatic( &SAutomationWindow::GenerateGroupOptionsMenuContent, InAutomationWindow ), LOCTEXT( "GroupOptions_Label", "Device Groups" ), LOCTEXT( "GroupOptionsToolTip", "Device Group Options" ), FSlateIcon(FEditorStyle::GetStyleSetName(), "AutomationWindow.GroupSettings")); } ToolbarBuilder.EndSection(); ToolbarBuilder.BeginSection("Search"); { ToolbarBuilder.AddWidget( Searchbox ); } ToolbarBuilder.EndSection(); ToolbarBuilder.BeginSection("Presets"); { ToolbarBuilder.AddWidget( PresetBox ); } ToolbarBuilder.EndSection(); ToolbarBuilder.BeginSection("History"); { ToolbarBuilder.AddWidget(HistoryBox); FUIAction DefaultAction; ToolbarBuilder.AddComboButton( DefaultAction, FOnGetContent::CreateStatic(&SAutomationWindow::GenerateTestHistoryMenuContent, InAutomationWindow), LOCTEXT("TestHistoryOptions_Label", "Test History Options"), LOCTEXT("TestHistoryOptionsToolTip", "Test History Options"), FSlateIcon(FEditorStyle::GetStyleSetName(), "AutomationWindow.TestHistoryOptions"), true); } ToolbarBuilder.EndSection(); } }; TSharedRef RunTests = SNew( SButton ) .ButtonStyle( FEditorStyle::Get(), "ToggleButton" ) .ToolTipText( LOCTEXT( "StartStop Tests", "Start / Stop tests" ) ) .OnClicked( this, &SAutomationWindow::RunTests ) .IsEnabled( this, &SAutomationWindow::IsAutomationRunButtonEnabled ) .ContentPadding(0) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .FillWidth(1) .VAlign(VAlign_Center) [ SNew( SVerticalBox ) + SVerticalBox::Slot() .AutoHeight() .HAlign( HAlign_Center ) [ SNew( SOverlay ) +SOverlay::Slot() [ SNew( SImage ) .Image( this, &SAutomationWindow::GetRunAutomationIcon ) ] +SOverlay::Slot() .HAlign(HAlign_Right) .VAlign(VAlign_Bottom) [ SNew( STextBlock ) .Text( this, &SAutomationWindow::OnGetNumEnabledTestsString ) .ColorAndOpacity( FLinearColor::White ) .ShadowOffset( FVector2D::UnitVector ) .Font( FEditorStyle::GetFontStyle( FName( "ToggleButton.LabelFont" ) ) ) ] ] + SVerticalBox::Slot() .AutoHeight() .HAlign( HAlign_Center ) [ SNew( STextBlock ) .Visibility( this, &SAutomationWindow::GetLargeToolBarVisibility ) .Text( this, &SAutomationWindow::GetRunAutomationLabel ) .Font( FEditorStyle::GetFontStyle( FName( "ToggleButton.LabelFont" ) ) ) .ColorAndOpacity(FLinearColor::White) .ShadowOffset( FVector2D::UnitVector ) ] ] ]; const float SearchWidth = 200.f; TSharedRef Searchbox = SNew(SHorizontalBox) +SHorizontalBox::Slot() .MaxWidth(SearchWidth) .FillWidth(1.f) .VAlign(VAlign_Bottom) [ SAssignNew( AutomationSearchBox, SSearchBox ) .ToolTipText( LOCTEXT( "Search Tests", "Search Tests" ) ) .OnTextChanged( this, &SAutomationWindow::OnFilterTextChanged ) .IsEnabled( this, &SAutomationWindow::IsAutomationControllerIdle ) .MinDesiredWidth(SearchWidth) ]; const float HistoryWidth = 200.0f; TSharedRef History = SNew(SHorizontalBox) + SHorizontalBox::Slot() .MaxWidth(HistoryWidth) .AutoWidth() .VAlign(VAlign_Bottom) [ SNew(SCheckBox) .Style(FEditorStyle::Get(), "ToggleButtonCheckbox") .Type(ESlateCheckBoxType::ToggleButton) .IsChecked(this, &SAutomationWindow::IsTrackingHistory) .IsEnabled(this, &SAutomationWindow::IsAutomationControllerIdle) .OnCheckStateChanged(this, &SAutomationWindow::OnToggleTrackHistory) [ SNew(SVerticalBox) + SVerticalBox::Slot() .VAlign(VAlign_Center) .HAlign(HAlign_Center) .FillHeight(1.f) .Padding(2.0f) [ SNew(SImage) .Image(FEditorStyle::GetBrush("AutomationWindow.TrackHistory")) ] + SVerticalBox::Slot() .Padding(2.0f) .VAlign(VAlign_Bottom) .AutoHeight() [ SNew(STextBlock) .ShadowOffset(FVector2D::UnitVector) .Text(LOCTEXT("AutomationHistoryLabel", "Track History")) .IsEnabled(this, &SAutomationWindow::IsAutomationControllerIdle) ] ] ]; TSharedRef TestPresets = SNew( SVerticalBox ) +SVerticalBox::Slot() .FillHeight(0.75f) .VAlign(VAlign_Bottom) .HAlign(HAlign_Left) [ SNew( SHorizontalBox ) +SHorizontalBox::Slot() .AutoWidth() .Padding(2.0f) .VAlign(VAlign_Bottom) [ SNew( STextBlock ) .Text( LOCTEXT("AutomationPresetLabel", "Preset:") ) .IsEnabled( this, &SAutomationWindow::IsAutomationControllerIdle ) ] ] +SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Bottom) [ SNew( SHorizontalBox ) +SHorizontalBox::Slot() .AutoWidth() [ //Preset Combo / Text SNew(SOverlay) +SOverlay::Slot() [ SNew(SHorizontalBox) .Visibility(this,&SAutomationWindow::HandlePresetComboVisibility) +SHorizontalBox::Slot() .FillWidth(1.0) [ SAssignNew( PresetComboBox, SComboBox< TSharedPtr > ) .OptionsSource( &TestPresetManager->GetAllPresets() ) .OnGenerateWidget( this, &SAutomationWindow::GeneratePresetComboItem ) .OnSelectionChanged( this, &SAutomationWindow::HandlePresetChanged ) .IsEnabled(this, &SAutomationWindow::IsAutomationControllerIdle) [ SNew( STextBlock ) .Text( this, &SAutomationWindow::GetPresetComboText ) ] ] ] +SOverlay::Slot() [ SNew(SHorizontalBox) .Visibility(this,&SAutomationWindow::HandlePresetTextVisibility) +SHorizontalBox::Slot() .FillWidth(1.0) [ SAssignNew(PresetTextBox, SEditableTextBox) .OnTextCommitted(this, &SAutomationWindow::HandlePresetTextCommited) .IsEnabled(this, &SAutomationWindow::IsAutomationControllerIdle) ] ] ] //New button +SHorizontalBox::Slot() .AutoWidth() [ SNew( SButton ) .ButtonStyle( FEditorStyle::Get(), "NoBorder" ) .OnClicked( this, &SAutomationWindow::HandleNewPresetClicked ) .ToolTipText( LOCTEXT("AutomationPresetNewButtonTooltip", "Create a new preset") ) .IsEnabled(this, &SAutomationWindow::IsAddButtonEnabled) .Content() [ SNew(SImage) .Image(FEditorStyle::Get().GetBrush("AutomationWindow.PresetNew")) ] ] //Save button +SHorizontalBox::Slot() .AutoWidth() [ SNew( SButton ) .ButtonStyle( FEditorStyle::Get(), "NoBorder" ) .OnClicked( this, &SAutomationWindow::HandleSavePresetClicked ) .ToolTipText( LOCTEXT("AutomationPresetSaveButtonTooltip", "Save the current test list") ) .IsEnabled(this, &SAutomationWindow::IsSaveButtonEnabled) .Content() [ SNew(SImage) .Image(FEditorStyle::Get().GetBrush("AutomationWindow.PresetSave")) ] ] //Remove button + SHorizontalBox::Slot() .AutoWidth() [ // remove button SNew(SButton) .ButtonStyle( FEditorStyle::Get(), "NoBorder" ) .OnClicked( this, &SAutomationWindow::HandleRemovePresetClicked ) .ToolTipText(LOCTEXT("AutomationPresetRemoveButtonTooltip", "Remove the selected preset")) .IsEnabled(this, &SAutomationWindow::IsRemoveButtonEnabled) .Content() [ SNew(SImage) .Image(FEditorStyle::Get().GetBrush("AutomationWindow.PresetRemove")) ] ] ]; FToolBarBuilder ToolbarBuilder( InCommandList, FMultiBoxCustomization::None ); TWeakPtr AutomationWindow = SharedThis(this); Local::FillToolbar( ToolbarBuilder, RunTests, Searchbox, TestPresets, History, AutomationWindow ); // Create the tool bar! return SNew( SHorizontalBox ) +SHorizontalBox::Slot() .AutoWidth() [ SNew( SBorder ) .Padding(0) .BorderImage( FEditorStyle::GetBrush("NoBorder") ) .IsEnabled( FSlateApplication::Get().GetNormalExecutionAttribute() ) [ ToolbarBuilder.MakeWidget() ] ]; } END_SLATE_FUNCTION_BUILD_OPTIMIZATION EVisibility SAutomationWindow::HandlePresetComboVisibility( ) const { return bAddingTestPreset ? EVisibility::Hidden : EVisibility::Visible; } EVisibility SAutomationWindow::HandlePresetTextVisibility( ) const { return bAddingTestPreset ? EVisibility::Visible : EVisibility::Hidden; } bool SAutomationWindow::IsAddButtonEnabled() const { return !bAddingTestPreset && IsAutomationControllerIdle(); } bool SAutomationWindow::IsSaveButtonEnabled() const { return (!bAddingTestPreset && SelectedPreset.IsValid() && IsAutomationControllerIdle()); } bool SAutomationWindow::IsRemoveButtonEnabled() const { return (!bAddingTestPreset && SelectedPreset.IsValid() && IsAutomationControllerIdle()); } void SAutomationWindow::HandlePresetTextCommited( const FText& CommittedText, ETextCommit::Type CommitType ) { if( CommitType == ETextCommit::OnEnter ) { bAddingTestPreset = false; if(CommittedText.IsEmpty()) { return; } TArray EnabledTests; AutomationController->GetEnabledTestNames(EnabledTests); AutomationPresetPtr NewPreset = TestPresetManager->AddNewPreset(CommittedText,EnabledTests); PresetComboBox->SetSelectedItem(NewPreset); SelectedPreset = NewPreset; PresetTextBox->SetText(FText()); } else if( CommitType == ETextCommit::OnCleared || CommitType == ETextCommit::OnUserMovedFocus ) { if( bAddingTestPreset ) { bAddingTestPreset = false; SelectedPreset = nullptr; PresetComboBox->ClearSelection(); PresetTextBox->SetText(FText()); } } } void SAutomationWindow::HandlePresetChanged( TSharedPtr Item, ESelectInfo::Type SelectInfo ) { if( Item.IsValid() ) { SelectedPreset = Item; AutomationController->SetEnabledTests(Item->GetEnabledTests()); TestTable->RequestTreeRefresh(); //Expand selected items TestTable->ClearExpandedItems(); TArray< TSharedPtr< IAutomationReport > >& TestReports = AutomationController->GetReports(); for( int32 Index = 0; Index < TestReports.Num(); Index++ ) { ExpandEnabledTests(TestReports[Index]); } } } void SAutomationWindow::ExpandEnabledTests( TSharedPtr< IAutomationReport > InReport ) { // Expand node if the report is enabled or contains an enabled test TestTable->SetItemExpansion( InReport, InReport->IsEnabled() || InReport->GetEnabledTestsNum() > 0 ); // Iterate through the child nodes to see if they should be expanded TArray > Reports = InReport->GetFilteredChildren(); for ( int32 ChildItem = 0; ChildItem < Reports.Num(); ChildItem++ ) { ExpandEnabledTests( Reports[ ChildItem ] ); } } FReply SAutomationWindow::HandleNewPresetClicked() { bAddingTestPreset = true; return FReply::Handled().SetUserFocus(PresetTextBox.ToSharedRef(), EFocusCause::SetDirectly); } FReply SAutomationWindow::HandleSavePresetClicked() { if(SelectedPreset.IsValid()) { TArray EnabledTests; AutomationController->GetEnabledTestNames(EnabledTests); SelectedPreset->SetEnabledTests(EnabledTests); TestPresetManager->SavePreset(SelectedPreset.ToSharedRef()); } return FReply::Handled(); } FReply SAutomationWindow::HandleRemovePresetClicked() { if(SelectedPreset.IsValid()) { TestPresetManager->RemovePreset(SelectedPreset.ToSharedRef()); SelectedPreset = nullptr; PresetComboBox->ClearSelection(); } return FReply::Handled(); } FText SAutomationWindow::GetPresetComboText() const { if( SelectedPreset.IsValid() ) { return SelectedPreset->GetPresetName(); } else { return LOCTEXT("AutomationPresetComboLabel", "