/** * Takes the provided menu builder and adds elements representing various * profiles that the user can choose from (default, tutorial, etc.). * * @param MenuBuilder The builder to modify and add entries to. */ static void BuildProfilesSubMenu(FMenuBuilder& MenuBuilder) { TArray<FString> AvailableProfiles; const UEditorPerProjectUserSettings* EditorPerProjectUserSettings = GetDefault<UEditorPerProjectUserSettings>(); if (EditorPerProjectUserSettings->BlueprintFavorites != NULL) { static FString const ProfilesConfigKey("Profiles"); GConfig->GetArray(*SBlueprintFavoritesPaletteUtils::ConfigSection, *ProfilesConfigKey, AvailableProfiles, GEditorIni); } struct LocalUtils { static bool CanExecute() { return true; } static bool CannotExecute() { return false; } static void NavigateToURL(FString URL) { FPlatformProcess::LaunchURL(*URL, NULL, NULL); } }; if (AvailableProfiles.Num() > 0) { for (FString const& Profile : AvailableProfiles) { FString ProfileName; FParse::Value(*Profile, TEXT("Name="), ProfileName); FString FriendlyProfileName; FParse::Value(*Profile, TEXT("FriendlyName="), FriendlyProfileName); FString ProfileToolTip; FParse::Value(*Profile, TEXT("ToolTip="), ProfileToolTip); FString ProfileURL; FParse::Value(*Profile, TEXT("URL="), ProfileURL); FString ProfileURLName; FParse::Value(*Profile, TEXT("URLText="), ProfileURLName); // @TODO how to best localize this? FText ToolTipText = FText::FromString(ProfileToolTip); if (ProfileURLName.IsEmpty()) { ProfileURLName = ProfileURL; } if (FriendlyProfileName.IsEmpty()) { FriendlyProfileName = ProfileName; } FUIAction ProfileAction; if (SBlueprintFavoritesPaletteUtils::CanLoadFavoritesProfile(ProfileName)) { if (ToolTipText.IsEmpty()) { ToolTipText = FText::Format(LOCTEXT("ProfileAvailableFmt", "Loads {0} node favorites"), FText::FromString(FriendlyProfileName)); } ProfileAction = FUIAction( FExecuteAction::CreateStatic(&SBlueprintFavoritesPaletteUtils::LoadFavoritesProfile, ProfileName), FCanExecuteAction::CreateStatic(&LocalUtils::CanExecute) ); } else { if (ToolTipText.IsEmpty()) { ToolTipText = LOCTEXT("ProfileLoaded", "Current profile"); } ProfileAction = FUIAction( FExecuteAction(), FCanExecuteAction::CreateStatic(&LocalUtils::CannotExecute) ); } // build the text that goes in the sub-menu TSharedRef<STextBlock> MenuTextEntry = SNew(STextBlock) .TextStyle(MenuBuilder.GetStyleSet(), FEditorStyle::Join("Menu", ".Label")) // @TODO how do we best localize this .Text(FText::FromString(FriendlyProfileName)); FSlateFontInfo ToolTipFont(FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Regular.ttf"), 8); TSharedPtr<SVerticalBox> ToolTipBox; // build the specialized tooltip TSharedRef<SToolTip> ToolTipWidget = SNew(SToolTip) [ SAssignNew(ToolTipBox, SVerticalBox) +SVerticalBox::Slot() [ SNew(STextBlock) .WrapTextAt(400) .Font(ToolTipFont) .Text(ToolTipText) ] ]; // add the url if one was specified if (!ProfileURL.IsEmpty()) { ToolTipBox->AddSlot() .AutoHeight() .HAlign(HAlign_Right) [ SNew(SHyperlink) // @TODO how to best localize this? .Text(FText::FromString(ProfileURLName)) .OnNavigate_Static(&LocalUtils::NavigateToURL, ProfileURL) ]; } // now build the actual menu widget TSharedRef<SWidget> MenuEntryWidget = SNew(SHorizontalBox) .ToolTip(ToolTipWidget) // so the tool tip shows up for the whole entry: .Visibility(EVisibility::Visible) +SHorizontalBox::Slot() // match the padding with normal sub-men entries .Padding(FMargin(18.f, 0.f, 6.f, 0.f)) .FillWidth(1.0f) [ MenuTextEntry ]; MenuBuilder.AddMenuEntry(ProfileAction, MenuEntryWidget); } } else { FUIAction NullProfileAction(FExecuteAction(), FCanExecuteAction::CreateStatic(&LocalUtils::CannotExecute)); MenuBuilder.AddMenuEntry(LOCTEXT("NoProfiles", "No profiles available"), FText::GetEmpty(), FSlateIcon(), NullProfileAction); } }