Exemplo n.º 1
0
void UEdGraphSchema::GetContextMenuActions(const UEdGraph* CurrentGraph, const UEdGraphNode* InGraphNode, const UEdGraphPin* InGraphPin, class FMenuBuilder* MenuBuilder, bool bIsDebugging) const
{
#if WITH_EDITOR
	FGraphNodeContextMenuBuilder Context(CurrentGraph, InGraphNode, InGraphPin, MenuBuilder, bIsDebugging);

	if (Context.Node)
	{
		Context.Node->GetContextMenuActions(Context);
	}

	if (InGraphNode)
	{
		// Helper to do the node comment editing
		struct Local
		{
			// Called by the EditableText widget to get the current comment for the node
			static FString GetNodeComment(TWeakObjectPtr<UEdGraphNode> NodeWeakPtr)
			{
				if (UEdGraphNode* SelectedNode = NodeWeakPtr.Get())
				{
					return SelectedNode->NodeComment;
				}
				return FString();
			}

			// Called by the EditableText widget when the user types a new comment for the selected node
			static void OnNodeCommentTextCommitted(const FText& NewText, ETextCommit::Type /*CommitInfo*/, TWeakObjectPtr<UEdGraphNode> NodeWeakPtr)
			{
				// Apply the change to the selected actor
				UEdGraphNode* SelectedNode = NodeWeakPtr.Get();
				FString NewString = NewText.ToString();
				if (SelectedNode && !SelectedNode->NodeComment.Equals( NewString, ESearchCase::CaseSensitive ))
				{
					// send property changed events
					const FScopedTransaction Transaction( LOCTEXT("EditNodeComment", "Change Node Comment") );
					SelectedNode->Modify();
					UProperty* NodeCommentProperty = FindField<UProperty>(SelectedNode->GetClass(), "NodeComment");
					if(NodeCommentProperty != NULL)
					{
						SelectedNode->PreEditChange(NodeCommentProperty);

						SelectedNode->NodeComment = NewString;

						FPropertyChangedEvent NodeCommentPropertyChangedEvent(NodeCommentProperty);
						SelectedNode->PostEditChangeProperty(NodeCommentPropertyChangedEvent);
					}
				}

				FSlateApplication::Get().DismissAllMenus();
			}
		};

		if( !InGraphPin )
		{
			int32 SelectionCount = GetNodeSelectionCount(CurrentGraph);
		
			if( SelectionCount == 1 )
			{
				// Node comment area
				TSharedRef<SHorizontalBox> NodeCommentBox = SNew(SHorizontalBox);

				MenuBuilder->BeginSection("GraphNodeComment", LOCTEXT("NodeCommentMenuHeader", "Node Comment"));
				{
					MenuBuilder->AddWidget(NodeCommentBox, FText::GetEmpty() );
				}
				TWeakObjectPtr<UEdGraphNode> SelectedNodeWeakPtr = InGraphNode;

				FText NodeCommentText;
				if ( UEdGraphNode* SelectedNode = SelectedNodeWeakPtr.Get() )
				{
					NodeCommentText = FText::FromString( SelectedNode->NodeComment );
				}

			const FSlateBrush* NodeIcon = FCoreStyle::Get().GetDefaultBrush();//@TODO: FActorIconFinder::FindIconForActor(SelectedActors(0).Get());


				// Comment label
				NodeCommentBox->AddSlot()
				.VAlign(VAlign_Center)
				.FillWidth( 1.0f )
				[
					SNew(SEditableTextBox)
					.Text( NodeCommentText )
					.ToolTipText(LOCTEXT("NodeComment_ToolTip", "Comment for this node"))
					.OnTextCommitted_Static(&Local::OnNodeCommentTextCommitted, SelectedNodeWeakPtr)
					.MinDesiredWidth( 120.f )
					//.IsReadOnly( !SelectedActors(0)->IsActorLabelEditable() )
					.SelectAllTextWhenFocused( true )
					.RevertTextOnEscape( true )
				];
				MenuBuilder->EndSection();
			}
			else if( SelectionCount > 1 )
			{
				struct SCommentUtility
				{
					static void CreateComment(const UEdGraphSchema* Schema, UEdGraph* Graph)
					{
						if( Schema && Graph )
						{
							TSharedPtr<FEdGraphSchemaAction> Action = Schema->GetCreateCommentAction();

							if( Action.IsValid() )
							{
								Action->PerformAction(Graph, NULL, FVector2D());
							}
						}
					}
				};

				MenuBuilder->BeginSection("SchemaActionComment", LOCTEXT("MultiCommentHeader", "Comment Group"));
				MenuBuilder->AddMenuEntry(	LOCTEXT("MultiCommentDesc", "Create Comment from Selection"),
											LOCTEXT("CommentToolTip", "Create a resizable comment box around selection."),
											FSlateIcon(), 
											FUIAction( FExecuteAction::CreateStatic( SCommentUtility::CreateComment, this, const_cast<UEdGraph*>( CurrentGraph ))));
				MenuBuilder->EndSection();
			}
		}
	}
#endif
}
Exemplo n.º 2
0
void SDetailNameArea::BuildObjectNameAreaSelectionLabel( TSharedRef< SHorizontalBox > SelectionLabelBox, const TWeakObjectPtr<UObject> ObjectWeakPtr, const int32 NumSelectedObjects ) 
{
	check( NumSelectedObjects > 1 || ObjectWeakPtr.IsValid() );

	if( NumSelectedObjects == 1 )
	{
		UClass* ObjectClass = ObjectWeakPtr.Get()->GetClass();
		if( ObjectClass != nullptr )
		{
			if (UBlueprint* Blueprint = Cast<UBlueprint>(ObjectClass->ClassGeneratedBy))
			{
				TWeakObjectPtr<UBlueprint> BlueprintPtr = Blueprint;

				SelectionLabelBox->AddSlot()
					.VAlign( VAlign_Center )
					.HAlign( HAlign_Left )
					.Padding( 6.0f, 1.0f, 0.0f, 0.0f )
					.FillWidth( 1.0f )
					[
						SNew(SHyperlink)
							.Style(FEditorStyle::Get(), "HoverOnlyHyperlink")
							.TextStyle(FEditorStyle::Get(), "DetailsView.EditBlueprintHyperlinkStyle")
							.OnNavigate(this, &SDetailNameArea::OnEditBlueprintClicked, BlueprintPtr, ObjectWeakPtr)
							.Text(FText::Format(LOCTEXT("EditBlueprint", "(Edit {0})"), FText::FromString( Blueprint->GetName() ) ))
							.ToolTipText(LOCTEXT("EditBlueprint_ToolTip", "Click to edit the blueprint"))
					];
			}		
			else if( FSourceCodeNavigation::IsCompilerAvailable() )
			{
				FString ClassHeaderPath;
				if( FSourceCodeNavigation::FindClassHeaderPath( ObjectClass, ClassHeaderPath ) && IFileManager::Get().FileSize( *ClassHeaderPath ) != INDEX_NONE )
				{
					struct Local
					{
						static void OnEditCodeClicked( FString ClassHeaderPath )
						{
							FString AbsoluteHeaderPath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead( *ClassHeaderPath );
							FSourceCodeNavigation::OpenSourceFile( AbsoluteHeaderPath );
						}
					};

					SelectionLabelBox->AddSlot()
						.VAlign( VAlign_Center )
						.HAlign( HAlign_Left )
						.Padding( 6.0f, 1.0f, 0.0f, 0.0f )
						.FillWidth( 1.0f )
						[
							SNew(SHyperlink)
								.Style(FEditorStyle::Get(), "HoverOnlyHyperlink")
								.TextStyle(FEditorStyle::Get(), "DetailsView.GoToCodeHyperlinkStyle")
								.OnNavigate_Static(&Local::OnEditCodeClicked, ClassHeaderPath)
//								.Text(LOCTEXT("GoToCode", "(C++)" ))
								.Text(FText::Format(LOCTEXT("GoToCode", "({0})" ), FText::FromString(FPaths::GetCleanFilename( *ClassHeaderPath ) ) ) )
								.ToolTipText(LOCTEXT("GoToCode_ToolTip", "Click to open this source file in a text editor"))
						];
				}
			}
			else
			{
				// Fill the empty space
				SelectionLabelBox->AddSlot();
			}
		}
		else
		{
			// Fill the empty space
			SelectionLabelBox->AddSlot();
		}
	}
	else
	{
		const FString SelectionText = FString::Printf( *LOCTEXT("MultipleObjectsSelected", "%d objects").ToString(), NumSelectedObjects );
		SelectionLabelBox->AddSlot()
		.VAlign(VAlign_Center)
		.HAlign( HAlign_Left )
		.FillWidth( 1.0f )
		[
			SNew(STextBlock)
			.Text( SelectionText )
		];

	}
}
	/** Overridden from SMultiColumnTableRow.  Generates a widget for this column of the list view. */
	virtual TSharedRef<SWidget> GenerateWidgetForColumn(const FName& ColumnName) override
	{
		if (ColumnName == FbxSceneImportSkeletalMesh::SceneImportCheckBoxSelectionHeaderIdName)
		{
			return SNew(SBox)
				.HAlign(HAlign_Center)
				[
					SNew(SCheckBox)
					.OnCheckStateChanged(this, &SFbxSleletalItemTableListViewRow::OnItemCheckChanged)
					.IsChecked(this, &SFbxSleletalItemTableListViewRow::IsItemChecked)
				];
		}
		else if (ColumnName == FbxSceneImportSkeletalMesh::SceneImportClassIconHeaderIdName)
		{
			UClass *IconClass = FbxMeshInfo->GetType();
			const FSlateBrush* ClassIcon = FClassIconFinder::FindIconForClass(IconClass);

			TSharedRef<SOverlay> IconContent = SNew(SOverlay)
				+ SOverlay::Slot()
				.HAlign(HAlign_Right)
				.VAlign(VAlign_Center)
				[
					SNew(SImage)
					.Image(ClassIcon)
				];


			// Add the component mobility icon
			IconContent->AddSlot()
				.HAlign(HAlign_Left)
				[
					SNew(SImage)
					.Image(this, &SFbxSleletalItemTableListViewRow::GetBrushForOverrideIcon)
				];
			return IconContent;
		}
		else if (ColumnName == FbxSceneImportSkeletalMesh::SceneImportAssetNameHeaderIdName)
		{
			return SNew(STextBlock)
				.Text(FText::FromString(FbxMeshInfo->Name))
				.ToolTipText(FText::FromString(FbxMeshInfo->Name));
		}
		else if (ColumnName == FbxSceneImportSkeletalMesh::SceneImportContentPathHeaderIdName)
		{
			return SNew(STextBlock)
				.Text(this, &SFbxSleletalItemTableListViewRow::GetAssetFullName)
				.ColorAndOpacity(this, &SFbxSleletalItemTableListViewRow::GetContentPathTextColor)
				.ToolTipText(this, &SFbxSleletalItemTableListViewRow::GetAssetFullName);
		}
		else if (ColumnName == FbxSceneImportSkeletalMesh::SceneImportOptionsNameHeaderIdName)
		{
			return SNew(STextBlock)
				.Text(this, &SFbxSleletalItemTableListViewRow::GetAssetOptionName)
				.ToolTipText(this, &SFbxSleletalItemTableListViewRow::GetAssetOptionName);
		}
		else if (ColumnName == FbxSceneBaseListViewColumn::PivotColumnId)
		{
			return SNew(STextBlock)
				.Text(this, &SFbxSleletalItemTableListViewRow::GetAssetPivotNodeName)
				.ToolTipText(this, &SFbxSleletalItemTableListViewRow::GetAssetPivotNodeName);
		}

		return SNullWidget::NullWidget;
	}
void FEditorUtilityInstanceDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayoutBuilder)
{
    SelectedObjectsList = DetailLayoutBuilder.GetDetailsView().GetSelectedObjects();

    // Hide some useless categories
    //@TODO: How to hide Actors, Layers, etc...?

    // Build a list of unique selected blutilities
    TArray<UClass*> UniqueBlutilityClasses;
    bool bFoundAnyCDOs = false;

    for (auto SelectedObjectIt = SelectedObjectsList.CreateConstIterator(); SelectedObjectIt; ++SelectedObjectIt)
    {
        UObject* Object = (*SelectedObjectIt).Get();

        if (!Object->HasAnyFlags(RF_ClassDefaultObject))
        {
            UClass* ObjectClass = Object->GetClass();

            if (UEditorUtilityBlueprint* Blutility = Cast<UEditorUtilityBlueprint>(ObjectClass->ClassGeneratedBy))
            {
                UniqueBlutilityClasses.Add(ObjectClass);
            }
        }
        else
        {
            bFoundAnyCDOs = true;
        }
    }

    // Run thru each one
    UniqueBlutilityClasses.Sort(FCompareClassNames());
    for (auto ClassIt = UniqueBlutilityClasses.CreateIterator(); ClassIt; ++ClassIt)
    {
        UClass* Class = *ClassIt;

        FString CategoryName = FString::Printf(TEXT("%sActions"), *Class->ClassGeneratedBy->GetName());
        IDetailCategoryBuilder& ActionsCategory = DetailLayoutBuilder.EditCategory(*CategoryName);

        const APlacedEditorUtilityBase* PlacedActorCDO = Cast<const APlacedEditorUtilityBase>(Class->GetDefaultObject());
        if (PlacedActorCDO)
        {
            ActionsCategory.AddCustomRow( PlacedActorCDO->HelpText )
            [
                SNew(STextBlock)
                .Text(PlacedActorCDO->HelpText)
            ];
        }

        const UGlobalEditorUtilityBase* GlobalBlutilityCDO = Cast<const UGlobalEditorUtilityBase>(Class->GetDefaultObject());
        if (GlobalBlutilityCDO)
        {
            ActionsCategory.AddCustomRow( GlobalBlutilityCDO->HelpText )
            [
                SNew(STextBlock)
                .Text(GlobalBlutilityCDO->HelpText)
            ];
        }

        TSharedRef<SWrapBox> WrapBox = SNew(SWrapBox).UseAllottedWidth(true);
        int32 NumButtons = 0;

        for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::IncludeSuper); FuncIt; ++FuncIt)
        {
            UFunction* Function = *FuncIt;

            const bool bCanExecute = (Function->NumParms == 0) && Function->HasAllFunctionFlags(FUNC_Exec);

            if (bCanExecute)
            {
                ++NumButtons;

                const FString ButtonCaption = FName::NameToDisplayString(*Function->GetName(), false);

                //@TODO: Expose the code in UK2Node_CallFunction::GetUserFacingFunctionName / etc...
                FString Tooltip = Function->GetToolTipText().ToString();
                if (Tooltip.IsEmpty())
                {
                    Tooltip = Function->GetName();
                }

                TWeakObjectPtr<UFunction> WeakFunctionPtr(Function);

                WrapBox->AddSlot()
                [
                    SNew(SButton)
                    .Text(ButtonCaption)
                    .OnClicked(	FOnClicked::CreateSP(this, &FEditorUtilityInstanceDetails::OnExecuteAction, WeakFunctionPtr) )
                    .ToolTipText(Tooltip)
                ];

            }
        }

        if (NumButtons > 0)
        {
            ActionsCategory.AddCustomRow(TEXT(""))
            [
                WrapBox
            ];
        }
    }

    // Hide the hint property
    if (!bFoundAnyCDOs)
    {
        DetailLayoutBuilder.HideProperty(TEXT("HelpText"));
    }
}
/* Construct the error widget from an array of errors*/
TSharedRef<SWidget> ConstructErrorWidget(const TArray<TSharedRef<FMaliOCReport::FErrorReport>>& Errors)
{
    TSharedRef<SVerticalBox> errorBox = SNew(SVerticalBox);

    for (const auto& error : Errors)
    {
        TSharedPtr<SVerticalBox> errorWarningBox = nullptr;

        errorBox->AddSlot()
            .Padding(WidgetPadding)
            .AutoHeight()
            [
                SNew(SExpandableArea)
                .AreaTitle(FText::FromString(error->TitleName))
                .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle")))
                .InitiallyCollapsed(false)
                .Padding(WidgetPadding)
                .BodyContent()
                [
                    SAssignNew(errorWarningBox, SVerticalBox)
                ]
            ];

        // Print the details of the shader (such as frequency)
        errorWarningBox->AddSlot()
            .AutoHeight()
            [
                GenerateFStringListView(error->Details)
            ];

        if (error->Errors.Num() > 0)
        {
            errorWarningBox->AddSlot()
                .AutoHeight()
                [
                    SNew(SSeparator)
                ];
            errorWarningBox->AddSlot()
                .AutoHeight()
                [
                    SNew(SExpandableArea)
                    .AreaTitle(FText::FromString(TEXT("Errors")))
                    .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle")))
                    .InitiallyCollapsed(false)
                    .Padding(WidgetPadding)
                    .BodyContent()
                    [
                        GenerateFStringListView(error->Errors)
                    ]
                ];
        }

        if (error->Warnings.Num() > 0)
        {
            errorWarningBox->AddSlot()
                .AutoHeight()
                [
                    SNew(SSeparator)
                ];
            errorWarningBox->AddSlot()
                .AutoHeight()
                [
                    SNew(SExpandableArea)
                    .AreaTitle(FText::FromString(TEXT("Warnings")))
                    .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle")))
                    .InitiallyCollapsed(false)
                    .Padding(WidgetPadding)
                    .BodyContent()
                    [
                        GenerateFStringListView(error->Warnings)
                    ]
                ];
        }

        AddSourceCodeToVerticalBox(errorWarningBox, error->SourceCode);
    }

    return errorBox;
}
Exemplo n.º 6
0
void FAssetEditorToolkit::GenerateToolbar()
{
	TSharedPtr<FExtender> Extender = FExtender::Combine(ToolbarExtenders);

	FToolBarBuilder ToolbarBuilder( GetToolkitCommands(), FMultiBoxCustomization::AllowCustomization( GetToolkitFName() ), Extender);
	ToolbarBuilder.SetIsFocusable(bIsToolbarFocusable);
	ToolbarBuilder.BeginSection("Asset");
	{
		if( IsActuallyAnAsset() )
		{
			ToolbarBuilder.AddToolBarButton(FAssetEditorCommonCommands::Get().SaveAsset);
			ToolbarBuilder.AddToolBarButton(FGlobalEditorCommonCommands::Get().FindInContentBrowser, NAME_None, LOCTEXT("FindInContentBrowserButton", "Find in CB"));
		}
	}
	ToolbarBuilder.EndSection();

	TSharedRef<SHorizontalBox> MiscWidgets = SNew(SHorizontalBox);

	for (int32 WidgetIdx = 0; WidgetIdx < ToolbarWidgets.Num(); ++WidgetIdx)
	{
		MiscWidgets->AddSlot()
		.AutoWidth()
		.VAlign(VAlign_Center)
		.Padding(0.0f, 2.0f, 0.0f, 2.0f)
		[
			ToolbarWidgets[WidgetIdx]
		];
	}
	
	Toolbar = 
		SNew(SHorizontalBox)
		+SHorizontalBox::Slot()
		.HAlign(HAlign_Left)
		.VAlign(VAlign_Center)
		[
			SNew(SVerticalBox)
			+SVerticalBox::Slot()
			.AutoHeight()
			.VAlign(VAlign_Bottom)
			[
				ToolbarBuilder.MakeWidget()
			]
		]
		+SHorizontalBox::Slot()
		.HAlign(HAlign_Right)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			SNew(SVerticalBox)
			+SVerticalBox::Slot()
			.AutoHeight()
			.VAlign(VAlign_Bottom)
			[
				SNew(SBorder)
				.BorderImage(FEditorStyle::GetBrush(TEXT("Toolbar.Background")))
				.Visibility(ToolbarWidgets.Num() > 0 ? EVisibility::Visible : EVisibility::Collapsed)
				[
					MiscWidgets
				]
			]
		];

	if (ToolbarWidgetContent.IsValid())
	{
		ToolbarWidgetContent->SetContent(Toolbar.ToSharedRef());
	}
}
Exemplo n.º 7
0
TSharedRef<SWidget> SKismetInspector::MakeContextualEditingWidget(struct FKismetSelectionInfo& SelectionInfo, const FShowDetailsOptions& Options)
{
	TSharedRef< SVerticalBox > ContextualEditingWidget = SNew( SVerticalBox );

	if(bShowTitleArea)
	{
		if (SelectedObjects.Num() == 0)
		{
			// Warning about nothing being selected
			ContextualEditingWidget->AddSlot()
			.AutoHeight()
			.HAlign( HAlign_Center )
			.Padding( 2.0f, 14.0f, 2.0f, 2.0f )
			[
				SNew( STextBlock )
				.Text( LOCTEXT("NoNodesSelected", "Select a node to edit details.") )
			];
		}
		else
		{
			// Title of things being edited
			ContextualEditingWidget->AddSlot()
			.AutoHeight()
			.Padding( 2.0f, 0.0f, 2.0f, 0.0f )
			[
				SNew(STextBlock)
				.Text(this, &SKismetInspector::GetContextualEditingWidgetTitle)
			];
		}
	}

	// Show the property editor
	PropertyView->HideFilterArea(Options.bHideFilterArea);
	PropertyView->SetObjects(SelectionInfo.ObjectsForPropertyEditing, Options.bForceRefresh);
	if (SelectionInfo.ObjectsForPropertyEditing.Num())
	{
		ContextualEditingWidget->AddSlot()
		.FillHeight( 0.9f )
		.VAlign( VAlign_Top )
		[
			SNew( SBox )
			.Visibility(this, &SKismetInspector::GetPropertyViewVisibility)
			[
				PropertyView.ToSharedRef()
			]
		];

		if (bShowPublicView)
		{
			ContextualEditingWidget->AddSlot()
			.AutoHeight()
			.VAlign( VAlign_Top )
			[
				SNew(SCheckBox)
				.ToolTipText(LOCTEXT("TogglePublicView", "Toggle Public View"))
				.IsChecked(this, &SKismetInspector::GetPublicViewCheckboxState)
				.OnCheckStateChanged( this, &SKismetInspector::SetPublicViewCheckboxState)
				[
					SNew(STextBlock)
					.Text(LOCTEXT("PublicViewCheckboxLabel", "Public View"))
				]
			];
		}
	}

	return ContextualEditingWidget;
}
Exemplo n.º 8
0
void FDragConnection::HoverTargetChanged()
{
	TArray<FPinConnectionResponse> UniqueMessages;

	if (UEdGraphPin* TargetPinObj = GetHoveredPin())
	{
		TArray<UEdGraphPin*> ValidSourcePins;
		ValidateGraphPinList(/*out*/ ValidSourcePins);

		// Check the schema for connection responses
		for (UEdGraphPin* StartingPinObj : ValidSourcePins)
		{
			if (TargetPinObj != StartingPinObj)
			{
				// The Graph object in which the pins reside.
				UEdGraph* GraphObj = StartingPinObj->GetOwningNode()->GetGraph();

				// Determine what the schema thinks about the wiring action
				const FPinConnectionResponse Response = GraphObj->GetSchema()->CanCreateConnection( StartingPinObj, TargetPinObj );

				if (Response.Response == ECanCreateConnectionResponse::CONNECT_RESPONSE_DISALLOW)
				{
					 TSharedPtr<SGraphNode> NodeWidget = TargetPinObj->GetOwningNode()->NodeWidget.Pin();
					 if (NodeWidget.IsValid())
					 {
						 NodeWidget->NotifyDisallowedPinConnection(StartingPinObj, TargetPinObj);
					 }
				}

				UniqueMessages.AddUnique(Response);
			}
		}
	}
	else if(UEdGraphNode* TargetNodeObj = GetHoveredNode())
	{
		TArray<UEdGraphPin*> ValidSourcePins;
		ValidateGraphPinList(/*out*/ ValidSourcePins);

		// Check the schema for connection responses
		for (UEdGraphPin* StartingPinObj : ValidSourcePins)
		{
			FPinConnectionResponse Response;
			FText ResponseText;
			if (StartingPinObj->GetOwningNode() != TargetNodeObj && StartingPinObj->GetSchema()->SupportsDropPinOnNode(TargetNodeObj, StartingPinObj->PinType, StartingPinObj->Direction, ResponseText))
			{
				Response.Response = ECanCreateConnectionResponse::CONNECT_RESPONSE_MAKE;
			}
			else
			{
				Response.Response = ECanCreateConnectionResponse::CONNECT_RESPONSE_DISALLOW;
			}
			
			// Do not display an error if there is no message
			if (!ResponseText.IsEmpty())
			{
				Response.Message = ResponseText;
				UniqueMessages.AddUnique(Response);
			}
		}
	}

	// Let the user know the status of dropping now
	if (UniqueMessages.Num() == 0)
	{
		// Display the place a new node icon, we're not over a valid pin
		SetSimpleFeedbackMessage(
			FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.NewNode")),
			FLinearColor::White,
			NSLOCTEXT("GraphEditor.Feedback", "PlaceNewNode", "Place a new node."));
	}
	else
	{
		// Take the unique responses and create visual feedback for it
		TSharedRef<SVerticalBox> FeedbackBox = SNew(SVerticalBox);
		for (auto ResponseIt = UniqueMessages.CreateConstIterator(); ResponseIt; ++ResponseIt)
		{
			// Determine the icon
			const FSlateBrush* StatusSymbol = NULL;

			switch (ResponseIt->Response)
			{
			case CONNECT_RESPONSE_MAKE:
			case CONNECT_RESPONSE_BREAK_OTHERS_A:
			case CONNECT_RESPONSE_BREAK_OTHERS_B:
			case CONNECT_RESPONSE_BREAK_OTHERS_AB:
				StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OK"));
				break;

			case CONNECT_RESPONSE_MAKE_WITH_CONVERSION_NODE:
				StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.ViaCast"));
				break;

			case CONNECT_RESPONSE_DISALLOW:
			default:
				StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error"));
				break;
			}

			// Add a new message row
			FeedbackBox->AddSlot()
			.AutoHeight()
			[
				SNew(SHorizontalBox)
				+SHorizontalBox::Slot()
				.AutoWidth()
				.Padding(3.0f)
				[
					SNew(SImage) .Image( StatusSymbol )
				]
				+SHorizontalBox::Slot()
				.AutoWidth()
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock) .Text( ResponseIt->Message )
				]
			];
		}

		SetFeedbackMessage(FeedbackBox);
	}
}
Exemplo n.º 9
0
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SAssetDialog::Construct(const FArguments& InArgs, const FSharedAssetDialogConfig& InConfig)
{
	DialogType = InConfig.GetDialogType();

	AssetClassNames = InConfig.AssetClassNames;

	const FString DefaultPath = InConfig.DefaultPath;

	FPathPickerConfig PathPickerConfig;
	PathPickerConfig.DefaultPath = DefaultPath;
	PathPickerConfig.bFocusSearchBoxWhenOpened = false;
	PathPickerConfig.OnPathSelected = FOnPathSelected::CreateSP(this, &SAssetDialog::HandlePathSelected);
	PathPickerConfig.SetPathsDelegates.Add(&SetPathsDelegate);

	FAssetPickerConfig AssetPickerConfig;
	AssetPickerConfig.Filter.ClassNames.Append(AssetClassNames);
	AssetPickerConfig.Filter.PackagePaths.Add(FName(*DefaultPath));
	AssetPickerConfig.bAllowDragging = false;
	AssetPickerConfig.InitialAssetViewType = EAssetViewType::Tile;
	AssetPickerConfig.ThumbnailScale = 0.125;
	AssetPickerConfig.OnAssetSelected = FOnAssetSelected::CreateSP(this, &SAssetDialog::OnAssetSelected);
	AssetPickerConfig.OnAssetsActivated = FOnAssetsActivated::CreateSP(this, &SAssetDialog::OnAssetsActivated);
	AssetPickerConfig.SetFilterDelegates.Add(&SetFilterDelegate);
	AssetPickerConfig.GetCurrentSelectionDelegates.Add(&GetCurrentSelectionDelegate);
	AssetPickerConfig.SaveSettingsName = TEXT("AssetDialog");
	AssetPickerConfig.bCanShowFolders = true;
	AssetPickerConfig.OnFolderEntered = FOnPathSelected::CreateSP(this, &SAssetDialog::HandleAssetViewFolderEntered);

	SetCurrentlySelectedPath(DefaultPath);

	// Open and save specific configuration
	FText ConfirmButtonText;
	bool bIncludeNameBox = false;
	if ( DialogType == EAssetDialogType::Open )
	{
		const FOpenAssetDialogConfig& OpenAssetConfig = static_cast<const FOpenAssetDialogConfig&>(InConfig);
		PathPickerConfig.bAllowContextMenu = false;
		ConfirmButtonText = LOCTEXT("AssetDialogOpenButton", "Open");
		AssetPickerConfig.SelectionMode = OpenAssetConfig.bAllowMultipleSelection ? ESelectionMode::Multi : ESelectionMode::Single;
		AssetPickerConfig.bFocusSearchBoxWhenOpened = true;
		bIncludeNameBox = false;
	}
	else if ( DialogType == EAssetDialogType::Save )
	{
		const FSaveAssetDialogConfig& SaveAssetConfig = static_cast<const FSaveAssetDialogConfig&>(InConfig);
		PathPickerConfig.bAllowContextMenu = true;
		ConfirmButtonText = LOCTEXT("AssetDialogSaveButton", "Save");
		AssetPickerConfig.SelectionMode = ESelectionMode::Single;
		AssetPickerConfig.bFocusSearchBoxWhenOpened = false;
		bIncludeNameBox = true;
		ExistingAssetPolicy = SaveAssetConfig.ExistingAssetPolicy;
		SetCurrentlyEnteredAssetName(SaveAssetConfig.DefaultAssetName);
	}
	else
	{
		ensureMsgf(0, TEXT("AssetDialog type %d is not supported."), DialogType);
	}

	TSharedPtr<SWidget> PathPicker = FContentBrowserSingleton::Get().CreatePathPicker(PathPickerConfig);
	TSharedPtr<SWidget> AssetPicker = FContentBrowserSingleton::Get().CreateAssetPicker(AssetPickerConfig);

	// The root widget in this dialog.
	TSharedRef<SVerticalBox> MainVerticalBox = SNew(SVerticalBox);

	// Path/Asset view
	MainVerticalBox->AddSlot()
		.FillHeight(1)
		.Padding(0, 0, 0, 4)
		[
			SNew(SSplitter)
		
			+SSplitter::Slot()
			.Value(0.25f)
			[
				SNew(SBorder)
				.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
				[
					PathPicker.ToSharedRef()
				]
			]

			+SSplitter::Slot()
			.Value(0.75f)
			[
				SNew(SBorder)
				.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
				[
					AssetPicker.ToSharedRef()
				]
			]
		];

	// Input error strip, if we are using a name box
	if (bIncludeNameBox)
	{
		// Name Error label
		MainVerticalBox->AddSlot()
		.AutoHeight()
		[
			// Constant height, whether the label is visible or not
			SNew(SBox).HeightOverride(18)
			[
				SNew(SBorder)
				.Visibility( this, &SAssetDialog::GetNameErrorLabelVisibility )
				.BorderImage( FEditorStyle::GetBrush("AssetDialog.ErrorLabelBorder") )
				.Content()
				[
					SNew(STextBlock)
					.Text( this, &SAssetDialog::GetNameErrorLabelText )
					.TextStyle( FEditorStyle::Get(), "AssetDialog.ErrorLabelFont" )
				]
			]
		];
	}

	// Buttons and asset name
	TSharedRef<SHorizontalBox> ButtonsAndNameBox = SNew(SHorizontalBox);

	if ( bIncludeNameBox )
	{
		ButtonsAndNameBox->AddSlot()
			.AutoWidth()
			.HAlign(HAlign_Right)
			.VAlign(VAlign_Center)
			.Padding(80, 3, 4, 3)
			[
				SNew(STextBlock).Text(LOCTEXT("NameBoxLabel", "Name:"))
			];

		ButtonsAndNameBox->AddSlot()
			.FillWidth(1)
			.VAlign(VAlign_Center)
			.Padding(4, 3)
			[
				SAssignNew(NameEditableText, SEditableTextBox)
				.Text(this, &SAssetDialog::GetAssetNameText)
				.OnTextCommitted(this, &SAssetDialog::OnAssetNameTextCommited)
				.OnTextChanged(this, &SAssetDialog::OnAssetNameTextCommited, ETextCommit::Default)
				.SelectAllTextWhenFocused(true)
			];
	}

	ButtonsAndNameBox->AddSlot()
		.AutoWidth()
		.VAlign(VAlign_Center)
		.Padding(4, 3)
		[
			SNew(SButton)
			.Text(ConfirmButtonText)
			.IsEnabled(this, &SAssetDialog::IsConfirmButtonEnabled)
			.OnClicked(this, &SAssetDialog::OnConfirmClicked)
		];

	ButtonsAndNameBox->AddSlot()
		.AutoWidth()
		.VAlign(VAlign_Center)
		.Padding(4, 3)
		[
			SNew(SButton)
			.Text(LOCTEXT("AssetDialogCancelButton", "Cancel"))
			.OnClicked(this, &SAssetDialog::OnCancelClicked)
		];

	MainVerticalBox->AddSlot()
		.AutoHeight()
		.HAlign(bIncludeNameBox ? HAlign_Fill : HAlign_Right)
		.Padding(8, 2, 8, 4)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
			[
				ButtonsAndNameBox
			]
		];

	ChildSlot
	[
		MainVerticalBox
	];
}
Exemplo n.º 10
0
void SModeWidget::Construct(const FArguments& InArgs, const FText& InText, const FName InMode)
{
	// Copy arguments
	ModeText = InText;
	ThisMode = InMode;
	OnGetActiveMode = InArgs._OnGetActiveMode;
	CanBeSelected = InArgs._CanBeSelected;
	OnSetActiveMode = InArgs._OnSetActiveMode;

	// Load resources
	InactiveModeBorderImage = FEditorStyle::GetBrush("ModeSelector.ToggleButton.Normal");
	ActiveModeBorderImage = FEditorStyle::GetBrush("ModeSelector.ToggleButton.Pressed");
	HoverBorderImage = FEditorStyle::GetBrush("ModeSelector.ToggleButton.Hovered");
	
	TSharedRef<SHorizontalBox> InnerRow = SNew(SHorizontalBox);

	FMargin IconPadding(4.0f, 0.0f, 4.0f, 0.0f);
	FMargin BodyPadding(0.0f, 0.0f, 0.0f, 0.0f);
	
	// Large Icon
	if (InArgs._IconImage.IsSet())
	{
		InnerRow->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.Padding(IconPadding)
			[
				SNew(SImage)
				.Image(InArgs._IconImage)
				.Visibility(this, &SModeWidget::GetLargeIconVisibility)
			];
	}

	// Small Icon
	if (InArgs._SmallIconImage.IsSet())
	{
		InnerRow->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.Padding(IconPadding)
			[
				SNew(SImage)
				.Image(InArgs._SmallIconImage)
				.Visibility(this, &SModeWidget::GetSmallIconVisibility)
			];
	}

	// Label + content
	InnerRow->AddSlot()
		.AutoWidth()
		.VAlign(VAlign_Center)
		.Padding(BodyPadding)
		[
			SNew(SVerticalBox)

			// Mode 'tab'
			+SVerticalBox::Slot()
			.AutoHeight()
			[
				SNew(SHorizontalBox)

				//Mode Name
				+SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(STextBlock)
					.Text(ModeText)
					.Font(this, &SModeWidget::GetDesiredTitleFont)
				]

				//Dirty flag
				+SHorizontalBox::Slot()
				.AutoWidth()
				.Padding(3)
				[
					SNew(SImage)
					.Image( InArgs._DirtyMarkerBrush )
				]
			]

			// Body of 'ribbon'
			+SVerticalBox::Slot()
			.AutoHeight()
			[

				InArgs._ShortContents.Widget
			]
		];


	// Create the widgets
	ChildSlot
	.VAlign(VAlign_Fill)
	[
		SNew(SBorder)
		.BorderImage(this, &SModeWidget::GetModeNameBorderImage)
		.OnMouseButtonDown(this, &SModeWidget::OnModeTabClicked)
		[
			InnerRow
		]
	];

	SetEnabled(CanBeSelected);
}
void SPropertyEditorAsset::Construct( const FArguments& InArgs, const TSharedPtr<FPropertyEditor>& InPropertyEditor )
{
	PropertyEditor = InPropertyEditor;
	PropertyHandle = InArgs._PropertyHandle;
	OnSetObject = InArgs._OnSetObject;
	OnShouldFilterAsset = InArgs._OnShouldFilterAsset;

	UProperty* Property = nullptr;
	if(PropertyEditor.IsValid())
	{
		Property = PropertyEditor->GetPropertyNode()->GetProperty();
		
		bAllowClear = !(Property->PropertyFlags & CPF_NoClear);
		ObjectClass = GetObjectPropertyClass(Property);
		bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() );
	}
	else
	{
		bAllowClear = InArgs._AllowClear;
		ObjectPath = InArgs._ObjectPath;
		ObjectClass = InArgs._Class;
		bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() );

		if (PropertyHandle.IsValid() && PropertyHandle->IsValidHandle())
		{
			Property = PropertyHandle->GetProperty();
		}
		else
		{
			CustomClassFilters.Add(ObjectClass);
		}
	}

	// Account for the allowed classes specified in the property metadata
	if (Property)
	{
		FString ClassFilterString;
		if (UArrayProperty* ArrayParent = Cast<UArrayProperty>(Property->GetOuter()))
		{
			ClassFilterString = ArrayParent->GetMetaData("AllowedClasses");
		}
		else
		{
			ClassFilterString = Property->GetMetaData("AllowedClasses");
		}

		if (ClassFilterString.IsEmpty())
		{
			CustomClassFilters.Add(ObjectClass);
		}
		else
		{
			TArray<FString> CustomClassFilterNames;
			ClassFilterString.ParseIntoArray(CustomClassFilterNames, TEXT(","), true);

			for (auto It = CustomClassFilterNames.CreateIterator(); It; ++It)
			{
				FString& ClassName = *It;
				// User can potentially list class names with leading or trailing whitespace
				ClassName.Trim();
				ClassName.TrimTrailing();

				UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName);

				if (!Class)
				{
					Class = LoadObject<UClass>(nullptr, *ClassName);
				}

				if (Class)
				{
					// If the class is an interface, expand it to be all classes in memory that implement the class.
					if (Class->HasAnyClassFlags(CLASS_Interface))
					{
						for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt)
						{
							UClass* const ClassWithInterface = (*ClassIt);
							if (ClassWithInterface->ImplementsInterface(Class))
							{
								CustomClassFilters.Add(ClassWithInterface);
							}
						}
					}
					else
					{
						CustomClassFilters.Add(Class);
					}
				}
			}
		}
	}

	if (InArgs._NewAssetFactories.IsSet())
	{
		NewAssetFactories = InArgs._NewAssetFactories.GetValue();
	}
	else if (CustomClassFilters.Num() > 1 || !CustomClassFilters.Contains(UObject::StaticClass()))
	{
		NewAssetFactories = PropertyCustomizationHelpers::GetNewAssetFactoriesForClasses(CustomClassFilters);
	}
	
	TSharedPtr<SHorizontalBox> ValueContentBox = NULL;
	ChildSlot
	[
		SNew( SAssetDropTarget )
		.OnIsAssetAcceptableForDrop( this, &SPropertyEditorAsset::OnAssetDraggedOver )
		.OnAssetDropped( this, &SPropertyEditorAsset::OnAssetDropped )
		[
			SAssignNew( ValueContentBox, SHorizontalBox )	
		]
	];

	TAttribute<bool> IsEnabledAttribute(this, &SPropertyEditorAsset::CanEdit);
	TAttribute<FText> TooltipAttribute(this, &SPropertyEditorAsset::OnGetToolTip);

	if (Property && Property->HasAllPropertyFlags(CPF_DisableEditOnTemplate))
	{
		// There are some cases where editing an Actor Property is not allowed, such as when it is contained within a struct or a CDO
		TArray<UObject*> ObjectList;
		PropertyEditor->GetPropertyHandle()->GetOuterObjects(ObjectList);

		// If there is no objects, that means we must have a struct asset managing this property
		if (ObjectList.Num() == 0)
		{
			IsEnabledAttribute.Set(false);
			TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplate", "Editing this value in structure's defaults is not allowed"));
		}
		else
		{
			// Go through all the found objects and see if any are a CDO, we can't set an actor in a CDO default.
			for (UObject* Obj : ObjectList)
			{
				if (Obj->HasAllFlags(RF_ClassDefaultObject))
				{
					IsEnabledAttribute.Set(false);
					TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplateTooltip", "Editing this value in a Class Default Object is not allowed"));
					break;
				}

			}
		}
	}
	bool bOldEnableAttribute = IsEnabledAttribute.Get();
	if (bOldEnableAttribute && !InArgs._EnableContentPicker)
	{
		IsEnabledAttribute.Set(false);
	}

	AssetComboButton = SNew(SComboButton)
		.ToolTipText(TooltipAttribute)
		.ButtonStyle( FEditorStyle::Get(), "PropertyEditor.AssetComboStyle" )
		.ForegroundColor(FEditorStyle::GetColor("PropertyEditor.AssetName.ColorAndOpacity"))
		.OnGetMenuContent( this, &SPropertyEditorAsset::OnGetMenuContent )
		.OnMenuOpenChanged( this, &SPropertyEditorAsset::OnMenuOpenChanged )
		.IsEnabled( IsEnabledAttribute )
		.ContentPadding(2.0f)
		.ButtonContent()
		[
			// Show the name of the asset or actor
			SNew(STextBlock)
			.TextStyle( FEditorStyle::Get(), "PropertyEditor.AssetClass" )
			.Font( FEditorStyle::GetFontStyle( PropertyEditorConstants::PropertyFontStyle ) )
			.Text(this,&SPropertyEditorAsset::OnGetAssetName)
		];

	if (bOldEnableAttribute && !InArgs._EnableContentPicker)
	{
		IsEnabledAttribute.Set(true);
	}

	TSharedRef<SHorizontalBox> ButtonBox = SNew( SHorizontalBox );
	
	TSharedPtr<SVerticalBox> CustomContentBox;

	if( ShouldDisplayThumbnail(InArgs) )
	{
		FObjectOrAssetData Value; 
		GetValue( Value );

		AssetThumbnail = MakeShareable( new FAssetThumbnail( Value.AssetData, InArgs._ThumbnailSize.X, InArgs._ThumbnailSize.Y, InArgs._ThumbnailPool ) );

		ValueContentBox->AddSlot()
		.Padding( 0.0f, 0.0f, 2.0f, 0.0f )
		.AutoWidth()
		[
			SAssignNew( ThumbnailBorder, SBorder )
			.Padding( 5.0f )
			.BorderImage( this, &SPropertyEditorAsset::GetThumbnailBorder )
			.OnMouseDoubleClick( this, &SPropertyEditorAsset::OnAssetThumbnailDoubleClick )
			[
				SNew( SBox )
				.ToolTipText(TooltipAttribute)
				.WidthOverride( InArgs._ThumbnailSize.X ) 
				.HeightOverride( InArgs._ThumbnailSize.Y )
				[
					AssetThumbnail->MakeThumbnailWidget()
				]
			]
		];


		ValueContentBox->AddSlot()
		[
			SNew( SBox )
			.VAlign( VAlign_Center )
			[
				SAssignNew( CustomContentBox, SVerticalBox )
				+ SVerticalBox::Slot()
				[
					AssetComboButton.ToSharedRef()
				]
				+ SVerticalBox::Slot()
				.AutoHeight()
				.Padding( 0.0f, 2.0f, 4.0f, 2.0f )
				[
					ButtonBox
				]
			]
		];
	}
	else
	{
		ValueContentBox->AddSlot()
		[
			SAssignNew( CustomContentBox, SVerticalBox )
			+SVerticalBox::Slot()
			.VAlign( VAlign_Center )
			[
				SNew( SHorizontalBox )
				+ SHorizontalBox::Slot()
				[
					AssetComboButton.ToSharedRef()
				]
				+ SHorizontalBox::Slot()
				.AutoWidth()
				.Padding( 4.f, 0.f )
				[
					ButtonBox
				]
			]
		];
	}

	if( InArgs._CustomContentSlot.Widget != SNullWidget::NullWidget )
	{
		CustomContentBox->AddSlot()
		.VAlign( VAlign_Center )
		.Padding( FMargin( 0.0f, 2.0f ) )
		[
			InArgs._CustomContentSlot.Widget
		];
	}

	if( !bIsActor && InArgs._DisplayUseSelected )
	{
		ButtonBox->AddSlot()
		.VAlign(VAlign_Center)
		.AutoWidth()
		.Padding( 2.0f, 0.0f )
		[
			PropertyCustomizationHelpers::MakeUseSelectedButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnUse ), FText(), IsEnabledAttribute )
		];
	}

	if( InArgs._DisplayBrowse )
	{
		ButtonBox->AddSlot()
		.Padding( 2.0f, 0.0f )
		.AutoWidth()
		.VAlign(VAlign_Center)
		[
			PropertyCustomizationHelpers::MakeBrowseButton(
				FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnBrowse ),
				TAttribute<FText>( this, &SPropertyEditorAsset::GetOnBrowseToolTip )
				)
		];
	}

	if( bIsActor )
	{
		TSharedRef<SWidget> ActorPicker = PropertyCustomizationHelpers::MakeInteractiveActorPicker( FOnGetAllowedClasses::CreateSP(this, &SPropertyEditorAsset::OnGetAllowedClasses), FOnShouldFilterActor(), FOnActorSelected::CreateSP( this, &SPropertyEditorAsset::OnActorSelected ) );
		ActorPicker->SetEnabled( IsEnabledAttribute );

		ButtonBox->AddSlot()
		.Padding( 2.0f, 0.0f )
		.AutoWidth()
		.VAlign(VAlign_Center)
		[
			ActorPicker
		];
	}

	if(InArgs._ResetToDefaultSlot.Widget != SNullWidget::NullWidget )
	{
		TSharedRef<SWidget> ResetToDefaultWidget  = InArgs._ResetToDefaultSlot.Widget;
		ResetToDefaultWidget->SetEnabled( IsEnabledAttribute );

		ButtonBox->AddSlot()
		.Padding( 4.0f, 0.0f )
		.AutoWidth()
		.VAlign(VAlign_Center)
		[
			ResetToDefaultWidget
		];
	}
}
Exemplo n.º 12
0
	/**
	 * Returns the internals of the notification
	 */
	TSharedRef<SHorizontalBox> ConstructInternals( const FArguments& InArgs ) 
	{
		CheckBoxStateChanged = InArgs._CheckBoxStateChanged;
		Hyperlink = InArgs._Hyperlink;
		HyperlinkText = InArgs._HyperlinkText;

		TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);

		// Notification image
		HorizontalBox->AddSlot()
		.AutoWidth()
		.Padding(10.f, 0.f, 0.f, 0.f)
		.VAlign(VAlign_Center)
		.HAlign(HAlign_Left)
		[
			SNew(SImage)
			.Image( InArgs._Image )
		];

		{
			const FSlateFontInfo Font = InArgs._bUseLargeFont.Get() 
				? FCoreStyle::Get().GetFontStyle(TEXT("NotificationList.FontBold")) 
				: FCoreStyle::Get().GetFontStyle(TEXT("NotificationList.FontLight"));

			// Container for the text and optional interactive widgets (buttons, check box, and hyperlink)
			TSharedRef<SVerticalBox> TextAndInteractiveWidgetsBox = SNew(SVerticalBox);

			HorizontalBox->AddSlot()
			.AutoWidth()
			.Padding(10.f, 0.f, 15.f, 0.f)
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Left)
			[
				TextAndInteractiveWidgetsBox
			];

			// Build Text box
			TextAndInteractiveWidgetsBox->AddSlot()
			.AutoHeight()
			[
				SNew(SBox)
				.WidthOverride(InArgs._WidthOverride)
				[
					SAssignNew(MyTextBlock, STextBlock)
					.Text(Text)
					.Font(Font)
					.AutoWrapText(InArgs._WidthOverride.IsSet()) // only auto-wrap the text if we've been given a size constraint; otherwise, fill the notification area
				]
			];

			TSharedRef<SHorizontalBox> InteractiveWidgetsBox = SNew(SHorizontalBox);
			TextAndInteractiveWidgetsBox->AddSlot()
			.AutoHeight()
			[
				InteractiveWidgetsBox
			];

			// Adds any buttons that were passed in.
			{
				TSharedRef<SHorizontalBox> ButtonsBox = SNew(SHorizontalBox);
				for (int32 idx = 0; idx < InArgs._ButtonDetails.Get().Num(); idx++)
				{
					FNotificationButtonInfo Button = InArgs._ButtonDetails.Get()[idx];

					ButtonsBox->AddSlot()
					.AutoWidth()
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
					.Padding(0.0f, 0.0f, 4.0f, 0.0f)
					[
						SNew(SButton)
						.Text(Button.Text)
						.ToolTipText(Button.ToolTip)
						.OnClicked(this, &SNotificationItemImpl::OnButtonClicked, Button.Callback) 
						.Visibility( this, &SNotificationItemImpl::GetButtonVisibility, Button.VisibilityOnNone, Button.VisibilityOnPending, Button.VisibilityOnSuccess, Button.VisibilityOnFail )
					];
				}
				InteractiveWidgetsBox->AddSlot()
				.AutoWidth()
				.Padding(0.0f, 2.0f, 0.0f, 0.0f)
				.VAlign(VAlign_Center)
				.HAlign(HAlign_Left)
				[
					ButtonsBox
				];
			}

			// Adds a check box, but only visible when bound
			InteractiveWidgetsBox->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Left)
			[
				SNew(SBox)
				.Padding(FMargin(0.0f, 2.0f, 4.0f, 0.0f))
				.VAlign(VAlign_Center)
				.HAlign(HAlign_Left)
				.Visibility(this, &SNotificationItemImpl::GetCheckBoxVisibility)
				[
					SNew(SCheckBox)
					.IsChecked(InArgs._CheckBoxState)
					.OnCheckStateChanged(CheckBoxStateChanged)
					[
						SNew(STextBlock)
						.Text(InArgs._CheckBoxText)
					]
				]
			];

			// Adds a hyperlink, but only visible when bound
			InteractiveWidgetsBox->AddSlot()
			.VAlign(VAlign_Bottom)
			.HAlign(HAlign_Right)
			[
				SNew(SBox)
				.Padding(FMargin(0.0f, 2.0f, 0.0f, 2.0f))
				.VAlign(VAlign_Center)
				.HAlign(HAlign_Left)
				.Visibility(this, &SNotificationItemImpl::GetHyperlinkVisibility)
				[
					SNew(SHyperlink)
					.Text(this, &SNotificationItemImpl::GetHyperlinkText)
					.OnNavigate(this, &SNotificationItemImpl::OnHyperlinkClicked)
				]
			];
		}

		if (InArgs._bUseThrobber.Get())
		{
			// Build pending throbber
			HorizontalBox->AddSlot()
			.AutoWidth()
			[
				SNew(SBox)
				.Padding(FMargin(5.f, 0.f, 10.f, 0.f))
				.HAlign(HAlign_Center)
				.VAlign(VAlign_Center)
				.Visibility( this, &SNotificationItemImpl::GetThrobberVisibility )
				[
					SNew(SThrobber)
				]
			];
		}

		if (InArgs._bUseSuccessFailIcons.Get())
		{
			// Build success/fail image
			HorizontalBox->AddSlot()
			.AutoWidth()
			[
				SNew(SBox)
				.Padding(FMargin(8.f, 0.f, 10.f, 0.f))
				.HAlign(HAlign_Center)
				.VAlign(VAlign_Center)
				.Visibility( this, &SNotificationItemImpl::GetSuccessFailImageVisibility )
				[
					SNew(SImage)
					.Image( this, &SNotificationItemImpl::GetSuccessFailImage )
				]
			];
		}

		return HorizontalBox;
	}
TSharedRef<SWidget> FSequencerTrackNode::GetCustomOutlinerContent()
{
	TSharedPtr<FSequencerSectionKeyAreaNode> KeyAreaNode = GetTopLevelKeyNode();
	if (KeyAreaNode.IsValid())
	{
		// @todo - Sequencer - Support multiple sections/key areas?
		TArray<TSharedRef<IKeyArea>> KeyAreas = KeyAreaNode->GetAllKeyAreas();

		if (KeyAreas.Num() > 0)
		{
			// Create the widgets for the key editor and key navigation buttons
			TSharedRef<SHorizontalBox> BoxPanel = SNew(SHorizontalBox);

			if (KeyAreas[0]->CanCreateKeyEditor())
			{
				BoxPanel->AddSlot()
				.HAlign(HAlign_Right)
				.VAlign(VAlign_Center)
				[
					SNew(SBox)
					.WidthOverride(100)
					.HAlign(HAlign_Left)
					[
						KeyAreas[0]->CreateKeyEditor(&GetSequencer())
					]
				];
			}
			else
			{
				BoxPanel->AddSlot()
				[
					SNew(SSpacer)
				];
			}

			BoxPanel->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			[
				SNew(SKeyNavigationButtons, AsShared())
			];

			return SNew(SBox)
				.VAlign(VAlign_Center)
				.HAlign(HAlign_Right)
				[
					BoxPanel
				];
		}
	}
	else
	{
		FGuid ObjectBinding;
		TSharedPtr<FSequencerDisplayNode> ParentSeqNode = GetParent();

		if (ParentSeqNode.IsValid() && (ParentSeqNode->GetType() == ESequencerNode::Object))
		{
			ObjectBinding = StaticCastSharedPtr<FSequencerObjectBindingNode>(ParentSeqNode)->GetObjectBinding();
		}
		FBuildEditWidgetParams Params;
		Params.NodeIsHovered = TAttribute<bool>::Create(TAttribute<bool>::FGetter::CreateSP(this, &FSequencerDisplayNode::IsHovered));

		TSharedPtr<SWidget> Widget = AssociatedEditor.BuildOutlinerEditWidget(ObjectBinding, AssociatedTrack.Get(), Params);

		TSharedRef<SHorizontalBox> BoxPanel = SNew(SHorizontalBox);

		bool bHasKeyableAreas = false;

		TArray<TSharedRef<FSequencerSectionKeyAreaNode>> ChildKeyAreaNodes;
		FSequencerDisplayNode::GetChildKeyAreaNodesRecursively(ChildKeyAreaNodes);
		for (int32 ChildIndex = 0; ChildIndex < ChildKeyAreaNodes.Num() && !bHasKeyableAreas; ++ChildIndex)
		{
			TArray< TSharedRef<IKeyArea> > ChildKeyAreas = ChildKeyAreaNodes[ChildIndex]->GetAllKeyAreas();

			for (int32 ChildKeyAreaIndex = 0; ChildKeyAreaIndex < ChildKeyAreas.Num() && !bHasKeyableAreas; ++ChildKeyAreaIndex)
			{
				if (ChildKeyAreas[ChildKeyAreaIndex]->CanCreateKeyEditor())
				{
					bHasKeyableAreas = true;
				}
			}
		}

		if (Widget.IsValid())
		{
			BoxPanel->AddSlot()
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Right)
			[
				Widget.ToSharedRef()
			];
		}

		if (bHasKeyableAreas)
		{
			BoxPanel->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			[
				SNew(SKeyNavigationButtons, AsShared())
			];
		}

		return SNew(SBox)
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Right)
			[
				BoxPanel
			];
	}


	return SNew(SSpacer);
}
Exemplo n.º 14
0
TSharedRef< SWidget > SDetailNameArea::BuildObjectNameArea( const TArray< TWeakObjectPtr<UObject> >& SelectedObjects )
{
	// Get the common base class of the selected objects
	UClass* BaseClass = NULL;
	for( int32 ObjectIndex = 0; ObjectIndex < SelectedObjects.Num(); ++ObjectIndex )
	{
		TWeakObjectPtr<UObject> ObjectWeakPtr = SelectedObjects[ObjectIndex];
		if( ObjectWeakPtr.IsValid() )
		{
			UClass* ObjClass = ObjectWeakPtr->GetClass();

			if (!BaseClass)
			{
				BaseClass = ObjClass;
			}

			while (!ObjClass->IsChildOf(BaseClass))
			{
				BaseClass = BaseClass->GetSuperClass();
			}
		}
	}

	TSharedRef< SHorizontalBox > ObjectNameArea = SNew( SHorizontalBox );

	if (BaseClass)
	{
		// Get selection icon based on actor(s) classes and add before the selection label
		const FSlateBrush* ActorIcon = FClassIconFinder::FindIconForClass(BaseClass);

		ObjectNameArea->AddSlot()
		.AutoWidth()
		.HAlign(HAlign_Left)
		.VAlign(VAlign_Center)
		.Padding(0,0,0,0)
		.AspectRatio()
		[
			SNew(SImage)
			.Image(ActorIcon)
			.ToolTipText( FText::FromString( BaseClass->GetName() ) )
		];
	}


	// Add the selected object(s) type name, along with buttons for either opening C++ code or editing blueprints
	const int32 NumSelectedSurfaces = AssetSelectionUtils::GetNumSelectedSurfaces( GWorld );
	if( SelectedObjects.Num() > 0 )
	{
		if ( bShowActorLabel )
		{
			FEditorWidgetsModule& EdWidgetsModule = FModuleManager::LoadModuleChecked<FEditorWidgetsModule>(TEXT("EditorWidgets"));
			TSharedRef<IObjectNameEditableTextBox> ObjectNameBox = EdWidgetsModule.CreateObjectNameEditableTextBox(SelectedObjects);

			ObjectNameArea->AddSlot()
			.AutoWidth()
			.Padding(0,0,6,0)
			[
				SNew(SBox)
				.WidthOverride( 200.0f )
				.VAlign(VAlign_Center)
				[
					ObjectNameBox
				]
			];
		}

		const TWeakObjectPtr< UObject > ObjectWeakPtr = SelectedObjects.Num() == 1 ? SelectedObjects[0] : NULL;
		BuildObjectNameAreaSelectionLabel( ObjectNameArea, ObjectWeakPtr, SelectedObjects.Num() );

		if( bShowLockButton )
		{
			ObjectNameArea->AddSlot()
				.AutoWidth()
				.HAlign(HAlign_Right)
				[
					SNew( SButton )
					.ButtonStyle( FEditorStyle::Get(), "NoBorder" )
					.OnClicked(	OnLockButtonClicked )
					.ToolTipText( LOCTEXT("LockSelectionButton_ToolTip", "Locks the current selection into the Details panel") )
					[
						SNew( SImage )
						.Image( this, &SDetailNameArea::OnGetLockButtonImageResource )
					]
				];
		}
	}
	else
	{
		if ( SelectionTip.Get() && NumSelectedSurfaces == 0 )
		{
			ObjectNameArea->AddSlot()
			.FillWidth( 1.0f )
			.HAlign( HAlign_Center )
			.Padding( 2.0f, 24.0f, 2.0f, 2.0f )
			[
				SNew( STextBlock )
				.Text( LOCTEXT("NoObjectsSelected", "Select an object to view details.") )
			];
		}
		else
		{
			// Fill the empty space
			ObjectNameArea->AddSlot();
		}
	}
	
	return ObjectNameArea;
}
Exemplo n.º 15
0
/**
 * Constructs the widget
 *
 * @param InArgs   Declaration from which to construct this widget.              
 */
void SDetailsView::Construct(const FArguments& InArgs)
{
	DetailsViewArgs = InArgs._DetailsViewArgs;
	bViewingClassDefaultObject = false;

	PropertyUtilities = MakeShareable( new FPropertyDetailsUtilities( *this ) );
	
	ColumnSizeData.LeftColumnWidth = TAttribute<float>( this, &SDetailsView::OnGetLeftColumnWidth );
	ColumnSizeData.RightColumnWidth = TAttribute<float>( this, &SDetailsView::OnGetRightColumnWidth );
	ColumnSizeData.OnWidthChanged = SSplitter::FOnSlotResized::CreateSP( this, &SDetailsView::OnSetColumnWidth );

	// We want the scrollbar to always be visible when objects are selected, but not when there is no selection - however:
	//  - We can't use AlwaysShowScrollbar for this, as this will also show the scrollbar when nothing is selected
	//  - We can't use the Visibility construction parameter, as it gets translated into user visibility and can hide the scrollbar even when objects are selected
	// We instead have to explicitly set the visibility after the scrollbar has been constructed to get the exact behavior we want
	TSharedRef<SScrollBar> ExternalScrollbar = SNew(SScrollBar);
	ExternalScrollbar->SetVisibility( TAttribute<EVisibility>( this, &SDetailsView::GetScrollBarVisibility ) );

		FMenuBuilder DetailViewOptions( true, nullptr);

		if (DetailsViewArgs.bShowModifiedPropertiesOption)
		{
			DetailViewOptions.AddMenuEntry( 
				LOCTEXT("ShowOnlyModified", "Show Only Modified Properties"),
				LOCTEXT("ShowOnlyModified_ToolTip", "Displays only properties which have been changed from their default"),
				FSlateIcon(),
				FUIAction( 
					FExecuteAction::CreateSP( this, &SDetailsView::OnShowOnlyModifiedClicked ),
					FCanExecuteAction(),
					FIsActionChecked::CreateSP( this, &SDetailsView::IsShowOnlyModifiedChecked )
				),
				NAME_None,
				EUserInterfaceActionType::ToggleButton 
			);
		}

		if( DetailsViewArgs.bShowDifferingPropertiesOption )
		{
			DetailViewOptions.AddMenuEntry(
				LOCTEXT("ShowOnlyDiffering", "Show Only Differing Properties"),
				LOCTEXT("ShowOnlyDiffering_ToolTip", "Displays only properties in this instance which have been changed or added from the instance being compared"),
				FSlateIcon(),
				FUIAction(
					FExecuteAction::CreateSP(this, &SDetailsView::OnShowOnlyDifferingClicked),
					FCanExecuteAction(),
					FIsActionChecked::CreateSP(this, &SDetailsView::IsShowOnlyDifferingChecked)
				),
				NAME_None,
				EUserInterfaceActionType::ToggleButton
			);
		}

		DetailViewOptions.AddMenuEntry(
			LOCTEXT("ShowAllAdvanced", "Show All Advanced Details"),
			LOCTEXT("ShowAllAdvanced_ToolTip", "Shows all advanced detail sections in each category"),
			FSlateIcon(),
			FUIAction( 
			FExecuteAction::CreateSP( this, &SDetailsView::OnShowAllAdvancedClicked ),
			FCanExecuteAction(),
			FIsActionChecked::CreateSP( this, &SDetailsView::IsShowAllAdvancedChecked )
				),
			NAME_None,
			EUserInterfaceActionType::ToggleButton 
		);

		DetailViewOptions.AddMenuEntry(
			LOCTEXT("ShowAllChildrenIfCategoryMatches", "Show Child On Category Match"),
			LOCTEXT("ShowAllChildrenIfCategoryMatches_ToolTip", "Shows children if their category matches the search criteria"),
			FSlateIcon(),
			FUIAction( 
				FExecuteAction::CreateSP( this, &SDetailsView::OnShowAllChildrenIfCategoryMatchesClicked ),
				FCanExecuteAction(),
				FIsActionChecked::CreateSP( this, &SDetailsView::IsShowAllChildrenIfCategoryMatchesChecked )
			),
			NAME_None,
			EUserInterfaceActionType::ToggleButton 
			);

		DetailViewOptions.AddMenuEntry(
			LOCTEXT("CollapseAll", "Collapse All Categories"),
			LOCTEXT("CollapseAll_ToolTip", "Collapses all root level categories"),
			FSlateIcon(),
			FUIAction(FExecuteAction::CreateSP(this, &SDetailsView::SetRootExpansionStates, /*bExpanded=*/false, /*bRecurse=*/false )));

		DetailViewOptions.AddMenuEntry(
			LOCTEXT("ExpandAll", "Expand All Categories"),
			LOCTEXT("ExpandAll_ToolTip", "Expands all root level categories"),
			FSlateIcon(),
			FUIAction(FExecuteAction::CreateSP(this, &SDetailsView::SetRootExpansionStates, /*bExpanded=*/true, /*bRecurse=*/false )));

	FilterRow = SNew( SHorizontalBox )
		.Visibility( this, &SDetailsView::GetFilterBoxVisibility )
		+SHorizontalBox::Slot()
		.FillWidth( 1 )
		.VAlign( VAlign_Center )
		[
			// Create the search box
			SAssignNew( SearchBox, SSearchBox )
			.OnTextChanged( this, &SDetailsView::OnFilterTextChanged  )
			.AddMetaData<FTagMetaData>(TEXT("Details.Search"))
		]
		+SHorizontalBox::Slot()
		.Padding( 4.0f, 0.0f, 0.0f, 0.0f )
		.AutoWidth()
		[
			// Create the search box
			SNew( SButton )
			.OnClicked( this, &SDetailsView::OnOpenRawPropertyEditorClicked )
			.IsEnabled( this, &SDetailsView::IsPropertyEditingEnabled )
			.ToolTipText( LOCTEXT("RawPropertyEditorButtonLabel", "Open Selection in Property Matrix") )
			[
				SNew( SImage )
				.Image( FEditorStyle::GetBrush("DetailsView.EditRawProperties") )
			]
		];

	if (DetailsViewArgs.bShowOptions)
	{
		FilterRow->AddSlot()
			.HAlign(HAlign_Right)
			.AutoWidth()
			[
				SNew( SComboButton )
				.ContentPadding(0)
				.ForegroundColor( FSlateColor::UseForeground() )
				.ButtonStyle( FEditorStyle::Get(), "ToggleButton" )
				.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("ViewOptions")))
				.MenuContent()
				[
					DetailViewOptions.MakeWidget()
				]
				.ButtonContent()
				[
					SNew(SImage)
					.Image( FEditorStyle::GetBrush("GenericViewButton") )
				]
			];
	}

	// Create the name area which does not change when selection changes
	SAssignNew(NameArea, SDetailNameArea, &SelectedObjects)
		// the name area is only for actors
		.Visibility(this, &SDetailsView::GetActorNameAreaVisibility)
		.OnLockButtonClicked(this, &SDetailsView::OnLockButtonClicked)
		.IsLocked(this, &SDetailsView::IsLocked)
		.ShowLockButton(DetailsViewArgs.bLockable)
		.ShowActorLabel(DetailsViewArgs.bShowActorLabel)
		// only show the selection tip if we're not selecting objects
		.SelectionTip(!DetailsViewArgs.bHideSelectionTip);

	TSharedRef<SVerticalBox> VerticalBox = SNew(SVerticalBox);

	if( !DetailsViewArgs.bCustomNameAreaLocation )
	{
		VerticalBox->AddSlot()
		.AutoHeight()
		.Padding(0.0f, 0.0f, 0.0f, 4.0f)
		[
			NameArea.ToSharedRef()
		];
	}

	if( !DetailsViewArgs.bCustomFilterAreaLocation )
	{
		VerticalBox->AddSlot()
		.AutoHeight()
		.Padding(0.0f, 0.0f, 0.0f, 2.0f)
		[
			FilterRow.ToSharedRef()
		];
	}

	VerticalBox->AddSlot()
	.FillHeight(1)
	.Padding(0)
	[
		SNew(SOverlay)
		+ SOverlay::Slot()
		[
			ConstructTreeView(ExternalScrollbar)
		]
		+ SOverlay::Slot()
		.HAlign(HAlign_Right)
		[
			SNew(SBox)
			.WidthOverride(16.0f)
			[
				ExternalScrollbar
			]
		]
	];

	ChildSlot
	[
		VerticalBox
	];
}
Exemplo n.º 16
0
void SGraphPin::Construct(const FArguments& InArgs, UEdGraphPin* InPin)
{
	bUsePinColorForText = InArgs._UsePinColorForText;
	this->SetCursor(EMouseCursor::Default);

	Visibility = TAttribute<EVisibility>(this, &SGraphPin::GetPinVisiblity);

	GraphPinObj = InPin;
	check(GraphPinObj != NULL);

	const UEdGraphSchema* Schema = GraphPinObj->GetSchema();
	check(Schema);

	const bool bCanConnectToPin = !GraphPinObj->bNotConnectable;
	const bool bIsInput = (GetDirection() == EGPD_Input);

	// Create the pin icon widget
	TSharedRef<SWidget> ActualPinWidget =
		SAssignNew(PinImage, SImage)
		.Image(this, &SGraphPin::GetPinIcon)
		.IsEnabled(bCanConnectToPin)
		.ColorAndOpacity(this, &SGraphPin::GetPinColor)
		.OnMouseButtonDown(this, &SGraphPin::OnPinMouseDown)
		.Cursor(this, &SGraphPin::GetPinCursor);

	// Create the pin indicator widget (used for watched values)
	static const FName NAME_NoBorder("NoBorder");
	TSharedRef<SWidget> PinStatusIndicator =
		SNew(SButton)
		.ButtonStyle(FEditorStyle::Get(), NAME_NoBorder)
		.Visibility(this, &SGraphPin::GetPinStatusIconVisibility)
		.ContentPadding(0)
		.OnClicked(this, &SGraphPin::ClickedOnPinStatusIcon)
		[
			SNew(SImage)
			.Image(this, &SGraphPin::GetPinStatusIcon)
		];

	TSharedRef<SWidget> LabelWidget = SNew(STextBlock)
		.Text(this, &SGraphPin::GetPinLabel)
		.TextStyle(FEditorStyle::Get(), InArgs._PinLabelStyle)
		.Visibility(this, &SGraphPin::GetPinLabelVisibility)
		.ColorAndOpacity(this, &SGraphPin::GetPinTextColor);

	// Create the widget used for the pin body (status indicator, label, and value)
	TSharedRef<SWrapBox> LabelAndValue =
		SNew(SWrapBox)
		.PreferredWidth(150.f);

	if (!bIsInput)
	{
		LabelAndValue->AddSlot()
			.VAlign(VAlign_Center)
			[
				PinStatusIndicator
			];

		LabelAndValue->AddSlot()
			.VAlign(VAlign_Center)
			[
				LabelWidget
			];
	}
	else
	{
		LabelAndValue->AddSlot()
			.VAlign(VAlign_Center)
			[
				LabelWidget
			];

		TSharedRef<SWidget> ValueWidget = GetDefaultValueWidget();

		if (ValueWidget != SNullWidget::NullWidget)
		{
			LabelAndValue->AddSlot()
				.Padding(bIsInput ? FMargin(InArgs._SideToSideMargin, 0, 0, 0) : FMargin(0, 0, InArgs._SideToSideMargin, 0))
				.VAlign(VAlign_Center)
				[
					SNew(SBox)
					.Padding(0.0f)
					.IsEnabled(this, &SGraphPin::IsEditingEnabled)
					[
						ValueWidget
					]
				];
		}

		LabelAndValue->AddSlot()
			.VAlign(VAlign_Center)
			[
				PinStatusIndicator
			];
	}

	TSharedPtr<SWidget> PinContent;
	if (bIsInput)
	{
		// Input pin
		PinContent = SNew(SHorizontalBox)
			+SHorizontalBox::Slot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.Padding(0, 0, InArgs._SideToSideMargin, 0)
			[
				ActualPinWidget
			]
			+SHorizontalBox::Slot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			[
				LabelAndValue
			];
	}
	else
	{
		// Output pin
		PinContent = SNew(SHorizontalBox)
			+SHorizontalBox::Slot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			[
				LabelAndValue
			]
			+SHorizontalBox::Slot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.Padding(InArgs._SideToSideMargin, 0, 0, 0)
			[
				ActualPinWidget
			];
	}

	// Set up a hover for pins that is tinted the color of the pin.
	SBorder::Construct(SBorder::FArguments()
		.BorderImage(this, &SGraphPin::GetPinBorder)
		.BorderBackgroundColor(this, &SGraphPin::GetPinColor)
		.OnMouseButtonDown(this, &SGraphPin::OnPinNameMouseDown)
		[
			SNew(SLevelOfDetailBranchNode)
			.UseLowDetailSlot(this, &SGraphPin::UseLowDetailPinNames)
			.LowDetail()
			[
				//@TODO: Try creating a pin-colored line replacement that doesn't measure text / call delegates but still renders
				ActualPinWidget
			]
			.HighDetail()
				[
					PinContent.ToSharedRef()
				]
		]
	);

	TAttribute<FText> ToolTipAttribute = TAttribute<FText>::Create(TAttribute<FText>::FGetter::CreateSP(this, &SGraphPin::GetTooltipText));
	SetToolTipText(ToolTipAttribute);
}
Exemplo n.º 17
0
	/** Construct this widget */
	void Construct( const FArguments& InArgs )
	{
		OnCancelClickedDelegate = InArgs._OnCancelClickedDelegate;
		WeakStack = InArgs._ScopeStack;

		// This is a temporary widget that needs to be updated over its entire lifespan => has an active timer registered for its entire lifespan
		RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SSlowTaskWidget::UpdateProgress ) );

		TSharedRef<SVerticalBox> VerticalBox = SNew(SVerticalBox)

			// Construct the main progress bar and text
			+ SVerticalBox::Slot()
			.AutoHeight()
			[
				SNew(SVerticalBox)

				+ SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FMargin(0, 0, 0, 5.f))
				.VAlign(VAlign_Center)
				[
					SNew(SBox)
					.HeightOverride(24.f)
					[
						SNew(SHorizontalBox)

						+ SHorizontalBox::Slot()
						[
							SNew( STextBlock )
							.AutoWrapText(true)
							.Text( this, &SSlowTaskWidget::GetProgressText, 0 )
							// The main font size dynamically changes depending on the content
							.Font( this, &SSlowTaskWidget::GetMainTextFont )
						]

						+ SHorizontalBox::Slot()
						.Padding(FMargin(5.f, 0, 0, 0))
						.AutoWidth()
						[
							SNew( STextBlock )
							.Text( this, &SSlowTaskWidget::GetPercentageText )
							// The main font size dynamically changes depending on the content
							.Font( FSlateFontInfo( FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Light.ttf"), 14, EFontHinting::AutoLight ) )
						]
					]
				]

				+ SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(SBox)
					.HeightOverride(MainBarHeight)
					[
						SNew(SProgressBar)
						.BorderPadding(FVector2D::ZeroVector)
						.Percent( this, &SSlowTaskWidget::GetProgressFraction, 0 )
						.BackgroundImage( FEditorStyle::GetBrush("ProgressBar.ThinBackground") )
						.FillImage( FEditorStyle::GetBrush("ProgressBar.ThinFill") )
					]
				]
			]
			
			// Secondary progress bars
			+ SVerticalBox::Slot()
			.Padding(FMargin(0.f, 8.f, 0.f, 0.f))
			[
				SAssignNew(SecondaryBars, SVerticalBox)
			];
		

		if ( OnCancelClickedDelegate.IsBound() )
		{
			VerticalBox->AddSlot()
				.AutoHeight()
				.HAlign(HAlign_Center)
				.Padding(10.0f, 7.0f)
				[
					SNew(SButton)
					.Text( NSLOCTEXT("FeedbackContextProgress", "Cancel", "Cancel") )
					.HAlign(EHorizontalAlignment::HAlign_Center)
					.OnClicked(this, &SSlowTaskWidget::OnCancel)
				];
		}

		SBorder::Construct( SBorder::FArguments()
			.BorderImage(FEditorStyle::GetBrush("Menu.Background"))
			.VAlign(VAlign_Center)
			.Padding(FMargin(FixedPaddingH))
			[
				SNew(SBox).WidthOverride(FixedWidth) [ VerticalBox ]
			]
		);

		// Make sure all our bars are set up
		UpdateDynamicProgressBars();
	}
Exemplo n.º 18
0
	/** Constructs this widget with InArgs */
	void Construct( const FArguments& InArgs )
	{
		Style = InArgs._Style;
		HighlightedText = InArgs._HighlightedText;
		Label = InArgs._Label;
		HintColorAndOpacity = InArgs._HintColorAndOpacity;
		bAllowHintText = InArgs._AllowHintText;

		AssetThumbnail = InArgs._AssetThumbnail;
		bHasRenderedThumbnail = false;
		WidthLastFrame = 0;
		GenericThumbnailBorderPadding = 2.f;

		AssetThumbnail->OnAssetDataChanged().AddSP(this, &SAssetThumbnail::OnAssetDataChanged);

		const FAssetData& AssetData = AssetThumbnail->GetAssetData();

		UClass* Class = FindObject<UClass>(ANY_PACKAGE, *AssetData.AssetClass.ToString());
		FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
		TSharedPtr<IAssetTypeActions> AssetTypeActions;
		if ( Class != NULL )
		{
			AssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass(Class).Pin();
		}

		AssetColor = FLinearColor::White;
		if( InArgs._AssetTypeColorOverride.IsSet() )
		{
			AssetColor = InArgs._AssetTypeColorOverride.GetValue();
		}
		else if ( AssetTypeActions.IsValid() )
		{
			AssetColor = AssetTypeActions->GetTypeColor();
		}

		TSharedRef<SOverlay> OverlayWidget = SNew(SOverlay);

		UpdateThumbnailClass(AssetData.AssetName, Class);

		ClassThumbnailBrushOverride = InArgs._ClassThumbnailBrushOverride;

		// The generic representation of the thumbnail, for use before the rendered version, if it exists
		OverlayWidget->AddSlot()
		[
			SNew(SBorder)
			.BorderImage(GetAssetBackgroundBrush())
			.BorderBackgroundColor(AssetColor.CopyWithNewOpacity(0.3f))
			.Padding(GenericThumbnailBorderPadding)
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Center)
			.Visibility(this, &SAssetThumbnail::GetGenericThumbnailVisibility)
			[
				SNew(SOverlay)

				+SOverlay::Slot()
				[
					SAssignNew(GenericLabelTextBlock, STextBlock)
					.Text(GetLabelText())
					.Font(GetTextFont())
					.Justification(ETextJustify::Center)
					.ColorAndOpacity(FEditorStyle::GetColor(Style, ".ColorAndOpacity"))
					.ShadowOffset(FEditorStyle::GetVector(Style, ".ShadowOffset"))
					.ShadowColorAndOpacity( FEditorStyle::GetColor(Style, ".ShadowColorAndOpacity"))
					.HighlightText(HighlightedText)
				]

				+SOverlay::Slot()
				[
					SAssignNew(GenericThumbnailImage, SImage)
					.Image(this, &SAssetThumbnail::GetClassThumbnailBrush)
				]
			]
		];

		if ( InArgs._ThumbnailPool.IsValid() && !InArgs._ForceGenericThumbnail )
		{
			ViewportFadeAnimation = FCurveSequence();
			ViewportFadeCurve = ViewportFadeAnimation.AddCurve(0.f, 0.25f, ECurveEaseFunction::QuadOut);

			TSharedPtr<SViewport> Viewport = 
				SNew( SViewport )
				.EnableGammaCorrection(false);

			Viewport->SetViewportInterface( AssetThumbnail.ToSharedRef() );
			AssetThumbnail->GetViewportRenderTargetTexture(); // Access the render texture to push it on the stack if it isnt already rendered

			InArgs._ThumbnailPool->OnThumbnailRendered().AddSP(this, &SAssetThumbnail::OnThumbnailRendered);
			InArgs._ThumbnailPool->OnThumbnailRenderFailed().AddSP(this, &SAssetThumbnail::OnThumbnailRenderFailed);

			if ( ShouldRender() && (!InArgs._AllowFadeIn || InArgs._ThumbnailPool->IsRendered(AssetThumbnail)) )
			{
				bHasRenderedThumbnail = true;
				ViewportFadeAnimation.JumpToEnd();
			}

			// The viewport for the rendered thumbnail, if it exists
			OverlayWidget->AddSlot()
			[
				SAssignNew(RenderedThumbnailWidget, SBorder)
				.Padding(0)
				.BorderImage(FEditorStyle::GetBrush("NoBrush"))
				.ColorAndOpacity(this, &SAssetThumbnail::GetViewportColorAndOpacity)
				[
					Viewport.ToSharedRef()
				]
			];
		}

		if( ThumbnailClass.Get() && bIsClassType )
		{
			OverlayWidget->AddSlot()
			.VAlign(VAlign_Bottom)
			.HAlign(HAlign_Right)
			.Padding(TAttribute<FMargin>(this, &SAssetThumbnail::GetClassIconPadding))
			[
				SAssignNew(ClassIconWidget, SBorder)
				.BorderImage(FEditorStyle::GetNoBrush())
				[
					SNew(SImage)
					.Image(this, &SAssetThumbnail::GetClassIconBrush)
				]
			];
		}

		if( bAllowHintText )
		{
			OverlayWidget->AddSlot()
				.HAlign(HAlign_Center)
				.VAlign(VAlign_Top)
				.Padding(FMargin(2, 2, 2, 2))
				[
					SNew(SBorder)
					.BorderImage(FEditorStyle::GetBrush(Style, ".HintBackground"))
					.BorderBackgroundColor(this, &SAssetThumbnail::GetHintBackgroundColor) //Adjust the opacity of the border itself
					.ColorAndOpacity(HintColorAndOpacity) //adjusts the opacity of the contents of the border
					.Visibility(this, &SAssetThumbnail::GetHintTextVisibility)
					.Padding(0)
					[
						SAssignNew(HintTextBlock, STextBlock)
						.Text(GetLabelText())
						.Font(GetHintTextFont())
						.ColorAndOpacity(FEditorStyle::GetColor(Style, ".HintColorAndOpacity"))
						.ShadowOffset(FEditorStyle::GetVector(Style, ".HintShadowOffset"))
						.ShadowColorAndOpacity(FEditorStyle::GetColor(Style, ".HintShadowColorAndOpacity"))
						.HighlightText(HighlightedText)
					]
				];
		}

		// The asset color strip
		OverlayWidget->AddSlot()
		.HAlign(HAlign_Fill)
		.VAlign(VAlign_Bottom)
		[
			SAssignNew(AssetColorStripWidget, SBorder)
			.BorderImage(FEditorStyle::GetBrush("WhiteBrush"))
			.BorderBackgroundColor(AssetColor)
			.Padding(this, &SAssetThumbnail::GetAssetColorStripPadding)
		];

		if( InArgs._AllowAssetSpecificThumbnailOverlay && AssetTypeActions.IsValid() )
		{
			// Does the asset provide an additional thumbnail overlay?
			TSharedPtr<SWidget> AssetSpecificThumbnailOverlay = AssetTypeActions->GetThumbnailOverlay(AssetData);
			if( AssetSpecificThumbnailOverlay.IsValid() )
			{
				OverlayWidget->AddSlot()
				[
					AssetSpecificThumbnailOverlay.ToSharedRef()
				];
			}
		}

		ChildSlot
		[
			OverlayWidget
		];

		UpdateThumbnailVisibilities();

	}
void SMessageLogMessageListRow::CreateMessage(const TSharedRef<SHorizontalBox>& InHorzBox, const TSharedRef<IMessageToken>& InMessageToken, float Padding)
{
	TSharedPtr<SWidget> RowContent;
	FName IconBrushName;

	TAttribute<EVisibility> TokenContentVisbility;
	
	switch (InMessageToken->GetType())
	{
	case EMessageToken::Image:
	{
		const TSharedRef<FImageToken> ImageToken = StaticCastSharedRef<FImageToken>(InMessageToken);

		if (ImageToken->GetImageName() != NAME_None)
		{
			if (InMessageToken->GetOnMessageTokenActivated().IsBound())
			{
				RowContent = SNew(SButton)
					.OnClicked(this, &SMessageLogMessageListRow::HandleTokenButtonClicked, InMessageToken)
					.Content()
					[
						SNew(SImage)
						.Image(FEditorStyle::GetBrush(ImageToken->GetImageName()))
					];
			}
			else
			{
				RowContent = SNew(SImage)
					.Image(FEditorStyle::GetBrush(ImageToken->GetImageName()));
			}
		}
	}
		break;

	case EMessageToken::Object:
	{
		const TSharedRef<FUObjectToken> UObjectToken = StaticCastSharedRef<FUObjectToken>(InMessageToken);

		IconBrushName = FName("PropertyWindow.Button_Browse");

		UObject* Object = nullptr;

		// Due to blueprint reconstruction, we can't directly use the Object as it will get trashed during the blueprint reconstruction and the message token will no longer point to the right UObject.
		// Instead we will retrieve the object from the name which should always be good.
		if (UObjectToken->GetObject().IsValid())
		{
			if (!UObjectToken->ToText().ToString().Equals(UObjectToken->GetObject().Get()->GetName()))
			{
				Object = FindObject<UObject>(nullptr, *UObjectToken->GetOriginalObjectPathName());
			}
			else
			{
				Object = const_cast<UObject*>(UObjectToken->GetObject().Get());
			}
		}
		else
		{
			// We have no object (probably because is now stale), try finding the original object linked to this message token to see if it still exist
			Object = FindObject<UObject>(nullptr, *UObjectToken->GetOriginalObjectPathName());
		}

		RowContent = CreateHyperlink(InMessageToken, FUObjectToken::DefaultOnGetObjectDisplayName().IsBound()
			? FUObjectToken::DefaultOnGetObjectDisplayName().Execute(Object, true)
			: UObjectToken->ToText());
	}
		break;

	case EMessageToken::URL:
	{
		const TSharedRef<FURLToken> URLToken = StaticCastSharedRef<FURLToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Url");
		RowContent = CreateHyperlink(InMessageToken, FText::FromString(URLToken->GetURL()));
	}
		break;
	case EMessageToken::EdGraph:
	{
		IconBrushName = FName("PropertyWindow.Button_Browse");
		RowContent = CreateHyperlink(InMessageToken, InMessageToken->ToText());
	}
	break;
	case EMessageToken::Action:
	{
		const TSharedRef<FActionToken> ActionToken = StaticCastSharedRef<FActionToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Action");
		RowContent = SNew(SHyperlink)
			.Text(InMessageToken->ToText())
			.ToolTipText(ActionToken->GetActionDescription())
			.TextStyle(FEditorStyle::Get(), "MessageLog")
			.OnNavigate(this, &SMessageLogMessageListRow::HandleActionHyperlinkNavigate, ActionToken);

		TokenContentVisbility = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateRaw(this, &SMessageLogMessageListRow::GetActionLinkVisibility, ActionToken));
	}
		break;

	case EMessageToken::AssetName:
	{
		const TSharedRef<FAssetNameToken> AssetNameToken = StaticCastSharedRef<FAssetNameToken>(InMessageToken);

		IconBrushName = FName("PropertyWindow.Button_Browse");
		RowContent = CreateHyperlink(InMessageToken, AssetNameToken->ToText());
	}
		break;

#if WITH_EDITOR
	case EMessageToken::Documentation:
	{
		const TSharedRef<FDocumentationToken> DocumentationToken = StaticCastSharedRef<FDocumentationToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Docs");
		RowContent = SNew(SHyperlink)
			.Text(LOCTEXT("DocsLabel", "Docs"))
			.ToolTip(IDocumentation::Get()->CreateToolTip(
			LOCTEXT("DocumentationTokenToolTip", "Click to open documentation"),
			NULL,
			DocumentationToken->GetPreviewExcerptLink(),
			DocumentationToken->GetPreviewExcerptName())
			)
			.TextStyle(FEditorStyle::Get(), "MessageLog")
			.OnNavigate(this, &SMessageLogMessageListRow::HandleDocsHyperlinkNavigate, DocumentationToken->GetDocumentationLink());
	}
		break;

	case EMessageToken::Text:
	{
		if (InMessageToken->GetOnMessageTokenActivated().IsBound())
		{
			RowContent = CreateHyperlink(InMessageToken, InMessageToken->ToText());
		}
		else
		{
			FString MessageString = InMessageToken->ToText().ToString();

			// ^((?:[\w]\:|\\)(?:(?:\\[a-z_\-\s0-9\.]+)+)\.(?:cpp|h))\((\d+)\)
			// https://regex101.com/r/vV4cV7/1
			FRegexPattern FileAndLinePattern(TEXT("^((?:[\\w]\\:|\\\\)(?:(?:\\\\[a-z_\\-\\s0-9\\.]+)+)\\.(?:cpp|h))\\((\\d+)\\)"));
			FRegexMatcher FileAndLineRegexMatcher(FileAndLinePattern, MessageString);

			TSharedRef<SWidget> SourceLink = SNullWidget::NullWidget;

			if ( FileAndLineRegexMatcher.FindNext() )
			{
				FString FileName = FileAndLineRegexMatcher.GetCaptureGroup(1);
				int32 LineNumber = FCString::Atoi(*FileAndLineRegexMatcher.GetCaptureGroup(2));

				// Remove the hyperlink from the message, since we're splitting it into its own string.
				MessageString = MessageString.RightChop(FileAndLineRegexMatcher.GetMatchEnding());

				SourceLink = SNew(SHyperlink)
					.Style(FEditorStyle::Get(), "Common.GotoNativeCodeHyperlink")
					.TextStyle(FEditorStyle::Get(), "MessageLog")
					.OnNavigate_Lambda([=] { FSlateApplication::Get().GotoLineInSource(FileName, LineNumber); })
					.Text(FText::FromString(FileAndLineRegexMatcher.GetCaptureGroup(0)));
			}

			RowContent = SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(0)
			[
				SourceLink
			]

			+ SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(0)
			[
				SNew(STextBlock)
				.ColorAndOpacity(FSlateColor::UseSubduedForeground())
				.Text(FText::FromString(MessageString))
			];
		}
	}
		break;

	case EMessageToken::Tutorial:
	{
		const TSharedRef<FTutorialToken> TutorialToken = StaticCastSharedRef<FTutorialToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Tutorial");
		RowContent = SNew(SHyperlink)
			.Text(LOCTEXT("TutorialLabel", "Tutorial"))
			.ToolTipText(LOCTEXT("TutorialTokenToolTip", "Click to open tutorial"))
			.TextStyle(FEditorStyle::Get(), "MessageLog")
			.OnNavigate(this, &SMessageLogMessageListRow::HandleTutorialHyperlinkNavigate, TutorialToken->GetTutorialAssetName());
	}
		break;
#endif
	}

	if (RowContent.IsValid())
	{
		InHorzBox->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.Padding(Padding, 0.0f, 0.0f, 0.0f)
			[
				SNew(SHorizontalBox)
				.Visibility(TokenContentVisbility.IsBound() ? TokenContentVisbility : EVisibility::Visible)

				+ SHorizontalBox::Slot()
				.AutoWidth()
				.VAlign(VAlign_Center)
				[
					(IconBrushName == NAME_None)
					? SNullWidget::NullWidget
					: static_cast<TSharedRef<SWidget>>(SNew(SImage)
					.ColorAndOpacity(FSlateColor::UseForeground())
					.Image(FEditorStyle::GetBrush(IconBrushName)))
				]

				+ SHorizontalBox::Slot()
					.AutoWidth()
					.VAlign(VAlign_Center)
					.Padding(2.0f, 0.0f, 0.0f, 0.0f)
					[
						RowContent.ToSharedRef()
					]
			];
	}
}
/* Make the Midgard dump widget (where we dump the statistics for Midgard compilation) */
TSharedRef<SWidget> ConstructMidgardDumpWidget(const TArray<TSharedRef<FMaliOCReport::FMidgardReport>>& Reports, bool DumpSourceCode)
{
    TSharedRef<SVerticalBox> midgardBox = SNew(SVerticalBox);

    for (const auto& report : Reports)
    {
        TSharedPtr<SVerticalBox> reportWarningBox = nullptr;

        midgardBox->AddSlot()
            .Padding(WidgetPadding)
            .AutoHeight()
            [
                SNew(SExpandableArea)
                .AreaTitle(FText::FromString(report->TitleName))
                .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle")))
                .ToolTipText(FText::FromString(report->TitleName))
                .InitiallyCollapsed(false)
                .Padding(WidgetPadding)
                .BodyContent()
                [
                    SAssignNew(reportWarningBox, SVerticalBox)
                ]
            ];

        // Print the details of the shader (such as frequency)
        reportWarningBox->AddSlot()
            .AutoHeight()
            [
                GenerateFStringListView(report->Details)
            ];

        // If there's only one render target, don't make an expandable area
        if (report->RenderTargets.Num() == 1)
        {
            reportWarningBox->AddSlot()
                .AutoHeight()
                [
                    SNew(SSeparator)
                ];

            reportWarningBox->AddSlot()
                .AutoHeight()
                [
                    GenerateMidgardStatsTable(report->RenderTargets[0])
                ];
        }
        else
        {
            for (const auto& rt : report->RenderTargets)
            {
                reportWarningBox->AddSlot()
                    .AutoHeight()
                    [
                        SNew(SSeparator)
                    ];

                reportWarningBox->AddSlot()
                    .AutoHeight()
                    [
                        SNew(SExpandableArea)
                        .AreaTitle(FText::FromString(FString::Printf(TEXT("Render Target %u"), rt->Index)))
                        .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle")))
                        .InitiallyCollapsed(false)
                        .Padding(WidgetPadding)
                        .BodyContent()
                        [
                            GenerateMidgardStatsTable(rt)
                        ]
                    ];
            }
        }

        // Dump the warnings
        if (report->Warnings.Num() > 0)
        {
            reportWarningBox->AddSlot()
                .AutoHeight()
                [
                    SNew(SSeparator)
                ];
            reportWarningBox->AddSlot()
                .AutoHeight()
                [
                    SNew(SExpandableArea)
                    .AreaTitle(FText::FromString(TEXT("Warnings")))
                    .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle")))
                    .InitiallyCollapsed(false)
                    .Padding(WidgetPadding)
                    .BodyContent()
                    [
                        GenerateFStringListView(report->Warnings)
                    ]
                ];
        }

        if (DumpSourceCode)
        {
            AddSourceCodeToVerticalBox(reportWarningBox, report->SourceCode);
        }
    }

    return midgardBox;
}
TSharedRef<SWidget> SLocalizationDashboardTargetRow::GenerateWidgetForColumn( const FName& ColumnName )
{
	TSharedPtr<SWidget> Return;

	if (ColumnName == "Target")
	{
		// Target Name
		Return = SNew(SHyperlink)
			.Text(this, &SLocalizationDashboardTargetRow::GetTargetName)
			.OnNavigate(this, &SLocalizationDashboardTargetRow::OnNavigate);
	}
	else if(ColumnName == "Status")
	{
		ULocalizationTarget* const LocalizationTarget = GetTarget();
		if (LocalizationTarget)
		{
			// Status icon button.
			Return = SNew(SLocalizationTargetStatusButton, *LocalizationTarget);
		}
	}
	else if (ColumnName == "Cultures")
	{
		// Culture Names
		Return = SNew(STextBlock)
			.Text(this, &SLocalizationDashboardTargetRow::GetCulturesText);
	}
	else if(ColumnName == "WordCount")
	{
		// Progress Bar and Word Counts
		Return = SNew(STextBlock)
			.Text(this, &SLocalizationDashboardTargetRow::GetWordCountText);
	}
	else if(ColumnName == "Actions")
	{
		TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);
		Return = HorizontalBox;

		// Gather
		HorizontalBox->AddSlot()
			.FillWidth(1.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			[
				SNew(SButton)
				.ButtonStyle( FEditorStyle::Get(), TEXT("HoverHintOnly") )
				.ToolTipText( LOCTEXT("GatherButtonLabel", "Gather") )
				.OnClicked(this, &SLocalizationDashboardTargetRow::Gather)
				.Content()
				[
					SNew(SImage)
					.Image( FEditorStyle::GetBrush("LocalizationDashboard.GatherTarget") )
				]
			];

		// Refresh Word Counts
		HorizontalBox->AddSlot()
			.FillWidth(1.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			[
				SNew(SButton)
				.ButtonStyle( FEditorStyle::Get(), TEXT("HoverHintOnly") )
				.ToolTipText( LOCTEXT("RefreshWordCountButtonLabel", "Refresh") )
				.OnClicked(this, &SLocalizationDashboardTargetRow::RefreshWordCount)
				.Content()
				[
					SNew(SImage)
					.Image(FEditorStyle::GetBrush("LocalizationDashboard.RefreshWordCount"))
				]
			];

		// Import All
		HorizontalBox->AddSlot()
			.FillWidth(1.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			[
				SNew(SButton)
				.ButtonStyle( FEditorStyle::Get(), TEXT("HoverHintOnly") )
				.ToolTipText( LOCTEXT("ImportAllButtonLabel", "Import All") )
				.OnClicked(this, &SLocalizationDashboardTargetRow::ImportAll)
				.Content()
				[
					SNew(SImage)
					.Image( FEditorStyle::GetBrush("LocalizationDashboard.ImportForAllCultures") )
				]
			];

		// Export All
		HorizontalBox->AddSlot()
			.FillWidth(1.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			[
				SNew(SButton)
				.ButtonStyle( FEditorStyle::Get(), TEXT("HoverHintOnly") )
				.ToolTipText(LOCTEXT("ExportAllButtonLabel", "Export All"))
				.OnClicked(this, &SLocalizationDashboardTargetRow::ExportAll)
				.Content()
				[
					SNew(SImage)
					.Image(FEditorStyle::GetBrush("LocalizationDashboard.ExportForAllCultures"))
				]
			];

		// Compile
		HorizontalBox->AddSlot()
			.FillWidth(1.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			[
				SNew(SButton)
				.ButtonStyle( FEditorStyle::Get(), TEXT("HoverHintOnly") )
				.ToolTipText( LOCTEXT("CompileButtonLabel", "Compile") )
				.OnClicked(this, &SLocalizationDashboardTargetRow::Compile)
				.Content()
				[
					SNew(SImage)
					.Image( FEditorStyle::GetBrush("LocalizationDashboard.CompileTarget") )
				]
			];

		// Delete Target
		HorizontalBox->AddSlot()
			.FillWidth(1.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			[
				SNew(SButton)
				.ButtonStyle( FEditorStyle::Get(), TEXT("HoverHintOnly") )
				.ToolTipText(LOCTEXT("DeleteButtonLabel", "Delete"))
				.OnClicked(this, &SLocalizationDashboardTargetRow::EnqueueDeletion)
				.Content()
				[
					SNew(SImage)
					.Image(FEditorStyle::GetBrush("LocalizationDashboard.DeleteTarget"))
				]
			];
	}

	return Return.IsValid() ? Return.ToSharedRef() : SNullWidget::NullWidget;
}