123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
- #include "SExtDocumentationToolTip.h"
- #include "Misc/Paths.h"
- #include "HAL/FileManager.h"
- #include "Modules/ModuleManager.h"
- #include "Widgets/SBoxPanel.h"
- #include "Framework/Application/SlateApplication.h"
- #include "Widgets/Text/STextBlock.h"
- #include "Widgets/Layout/SBox.h"
- #include "Widgets/SToolTip.h"
- #include "EditorStyleSet.h"
- #include "Editor/EditorPerProjectUserSettings.h"
- #include "IDocumentationPage.h"
- #include "IDocumentation.h"
- #include "IDocumentationProvider.h"
- #include "DocumentationLink.h"
- #include "ISourceCodeAccessor.h"
- #include "ISourceCodeAccessModule.h"
- #include "SourceControlHelpers.h"
- #include "EngineAnalytics.h"
- #include "AnalyticsEventAttribute.h"
- #include "Interfaces/IAnalyticsProvider.h"
- #include "Widgets/Input/SHyperlink.h"
- #include "Framework/Notifications/NotificationManager.h"
- #include "Widgets/Notifications/SNotificationList.h"
- #include "ExtDocumentation.h"
- void SExtDocumentationToolTip::Construct( const FArguments& InArgs )
- {
- TextContent = InArgs._Text;
- StyleInfo = FAppStyle::GetWidgetStyle<FTextBlockStyle>(InArgs._Style);
- SubduedStyleInfo = FAppStyle::GetWidgetStyle<FTextBlockStyle>(InArgs._SubduedStyle);
- HyperlinkTextStyleInfo = FAppStyle::GetWidgetStyle<FTextBlockStyle>(InArgs._HyperlinkTextStyle);
- HyperlinkButtonStyleInfo = FAppStyle::GetWidgetStyle<FButtonStyle>(InArgs._HyperlinkButtonStyle);
- ColorAndOpacity = InArgs._ColorAndOpacity;
- DocumentationLink = InArgs._DocumentationLink;
- IsDisplayingDocumentationLink = false;
- bAddDocumentation = InArgs._AddDocumentation;
- DocumentationMargin = InArgs._DocumentationMargin;
- if ( !DocumentationLink.IsEmpty() )
- {
- // All in-editor udn documents must live under the Shared/ folder
- ensure( InArgs._DocumentationLink.StartsWith( TEXT("Shared/") ) );
- }
- ExcerptName = InArgs._ExcerptName;
- IsShowingFullTip = false;
- if( InArgs._Content.Widget != SNullWidget::NullWidget )
- {
- // Widget content argument takes precedence
- // overrides the text content.
- OverrideContent = InArgs._Content.Widget;
- }
- AlwaysShowFullToolTip = InArgs._AlwaysShowFullToolTip;
- ConstructSimpleTipContent();
- ChildSlot
- [
- SAssignNew(WidgetContent, SBox)
- [
- SimpleTipContent.ToSharedRef()
- ]
- ];
- // else
- // {
- // IsShowingFullTip = true;
- // ConstructFullTipContent();
- // ChildSlot
- // [
- // SAssignNew(WidgetContent, SBox)
- // [
- // FullTipContent.ToSharedRef()
- // ]
- // ];
- // }
-
- }
- void SExtDocumentationToolTip::ConstructSimpleTipContent()
- {
- TSharedPtr< SVerticalBox > VerticalBox;
- if ( !OverrideContent.IsValid() )
- {
- SAssignNew( SimpleTipContent, SBox )
- [
- SAssignNew( VerticalBox, SVerticalBox )
- +SVerticalBox::Slot()
- .FillHeight( 1.0f )
- [
- SNew( STextBlock )
- .Text( TextContent )
- .TextStyle( &StyleInfo )
- .ColorAndOpacity( ColorAndOpacity )
- .WrapTextAt_Static( &SToolTip::GetToolTipWrapWidth )
- ]
- ];
- }
- else
- {
- SAssignNew( SimpleTipContent, SBox )
- [
- SAssignNew( VerticalBox, SVerticalBox )
- +SVerticalBox::Slot()
- .FillHeight( 1.0f )
- [
- OverrideContent.ToSharedRef()
- ]
- ];
- }
- if (bAddDocumentation)
- {
- AddDocumentation(VerticalBox);
- }
- }
- void SExtDocumentationToolTip::AddDocumentation(TSharedPtr< SVerticalBox > VerticalBox)
- {
- if ( !DocumentationLink.IsEmpty() )
- {
- IsDisplayingDocumentationLink = GetDefault<UEditorPerProjectUserSettings>()->bDisplayDocumentationLink;
- if ( IsDisplayingDocumentationLink )
- {
- FString OptionalExcerptName;
- if ( !ExcerptName.IsEmpty() )
- {
- OptionalExcerptName = FString( TEXT(" [") ) + ExcerptName + TEXT("]");
- }
- VerticalBox->AddSlot()
- .AutoHeight()
- .Padding(0, 5, 0, 0)
- .HAlign( HAlign_Center )
- [
- SNew( STextBlock )
- .Text( FText::FromString(DocumentationLink + OptionalExcerptName) )
- .TextStyle( &SubduedStyleInfo )
- ];
- }
- if ( !DocumentationPage.IsValid() )
- {
- if (const IDocumentationProvider* Provider = FDocumentationProvider::Get().GetProvider(FName(*DocumentationHostPluginName)))
- {
- DocumentationPage = Provider->GetDocumentation()->GetPage(DocumentationLink, NULL);
- }
- }
- if (DocumentationPage.IsValid() && DocumentationPage->HasExcerpt( ExcerptName ) )
- {
- FText MacShortcut = NSLOCTEXT("SToolTip", "MacRichTooltipShortcut", "(Cmd + Alt)");
- FText WinShortcut = NSLOCTEXT("SToolTip", "WinRichTooltipShortcut", "(Ctrl + Alt)");
- FText KeyboardShortcut;
- #if PLATFORM_MAC
- KeyboardShortcut = MacShortcut;
- #else
- KeyboardShortcut = WinShortcut;
- #endif
- VerticalBox->AddSlot()
- .AutoHeight()
- .HAlign( HAlign_Center )
- .Padding(0, 5, 0, 0)
- [
- SNew( STextBlock )
- .TextStyle( &SubduedStyleInfo )
- .Text( FText::Format( NSLOCTEXT( "SToolTip", "AdvancedToolTipMessage", "hold {0} for more" ), KeyboardShortcut) )
- ];
- }
- else
- {
- if ( IsDisplayingDocumentationLink && FSlateApplication::Get().SupportsSourceAccess() )
- {
- FString DocPath = FExtDocumentationLink::ToSourcePath( DocumentationLink, FInternationalization::Get().GetCurrentCulture() );
- if ( !FPaths::FileExists(DocPath) )
- {
- DocPath = FPaths::ConvertRelativePathToFull(DocPath);
- }
- VerticalBox->AddSlot()
- .AutoHeight()
- .Padding(0, 5, 0, 0)
- .HAlign( HAlign_Center )
- [
- SNew( SHyperlink )
- .Text( NSLOCTEXT( "SToolTip", "EditDocumentationMessage_Create", "create" ) )
- .TextStyle( &HyperlinkTextStyleInfo )
- .UnderlineStyle( &HyperlinkButtonStyleInfo )
- .OnNavigate( this, &SExtDocumentationToolTip::CreateExcerpt, DocPath, ExcerptName )
- ];
- }
- }
- }
- }
- void SExtDocumentationToolTip::CreateExcerpt( FString FileSource, FString InExcerptName )
- {
- FText CheckoutFailReason;
- bool bNewFile = true;
- bool bCheckoutOrAddSucceeded = true;
- if (FPaths::FileExists(FileSource))
- {
- // Check out the existing file
- bNewFile = false;
- bCheckoutOrAddSucceeded = SourceControlHelpers::CheckoutOrMarkForAdd(FileSource, NSLOCTEXT("SToolTip", "DocumentationSCCActionDesc", "tool tip excerpt"), FOnPostCheckOut(), /*out*/ CheckoutFailReason);
- }
- FArchive* FileWriter = IFileManager::Get().CreateFileWriter( *FileSource, EFileWrite::FILEWRITE_Append | EFileWrite::FILEWRITE_AllowRead | EFileWrite::FILEWRITE_EvenIfReadOnly );
- if (bNewFile)
- {
- FString UdnHeader;
- UdnHeader += "Availability:NoPublish";
- UdnHeader += LINE_TERMINATOR;
- UdnHeader += "Title:";
- UdnHeader += LINE_TERMINATOR;
- UdnHeader += "Crumbs:";
- UdnHeader += LINE_TERMINATOR;
- UdnHeader += "Description:";
- UdnHeader += LINE_TERMINATOR;
- FileWriter->Serialize( TCHAR_TO_ANSI( *UdnHeader ), UdnHeader.Len() );
- }
- FString NewExcerpt;
- NewExcerpt += LINE_TERMINATOR;
- NewExcerpt += "[EXCERPT:";
- NewExcerpt += InExcerptName;
- NewExcerpt += "]";
- NewExcerpt += LINE_TERMINATOR;
- NewExcerpt += TextContent.Get().ToString();
- NewExcerpt += LINE_TERMINATOR;
- NewExcerpt += "[/EXCERPT:";
- NewExcerpt += InExcerptName;
- NewExcerpt += "]";
- NewExcerpt += LINE_TERMINATOR;
- if (!bNewFile)
- {
- FileWriter->Seek( FMath::Max( FileWriter->TotalSize(), (int64)0 ) );
- }
- FileWriter->Serialize( TCHAR_TO_ANSI( *NewExcerpt ), NewExcerpt.Len() );
- FileWriter->Close();
- delete FileWriter;
- if (bNewFile)
- {
- // Add the new file
- bCheckoutOrAddSucceeded = SourceControlHelpers::CheckoutOrMarkForAdd(FileSource, NSLOCTEXT("SToolTip", "DocumentationSCCActionDesc", "tool tip excerpt"), FOnPostCheckOut(), /*out*/ CheckoutFailReason);
- }
- ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
- SourceCodeAccessModule.GetAccessor().OpenFileAtLine(FileSource, 0);
- if (!bCheckoutOrAddSucceeded)
- {
- FNotificationInfo Info(CheckoutFailReason);
- Info.ExpireDuration = 3.0f;
- FSlateNotificationManager::Get().AddNotification(Info);
- }
- ReloadDocumentation();
- }
- void SExtDocumentationToolTip::ConstructFullTipContent()
- {
- TArray< FExcerpt > Excerpts;
- DocumentationPage->GetExcerpts( Excerpts );
- if ( Excerpts.Num() > 0 )
- {
- int32 ExcerptIndex = 0;
- if ( !ExcerptName.IsEmpty() )
- {
- for (int Index = 0; Index < Excerpts.Num(); Index++)
- {
- if ( Excerpts[ Index ].Name == ExcerptName )
- {
- ExcerptIndex = Index;
- break;
- }
- }
- }
- if ( !Excerpts[ ExcerptIndex ].Content.IsValid() )
- {
- DocumentationPage->GetExcerptContent( Excerpts[ ExcerptIndex ] );
- }
- if ( Excerpts[ ExcerptIndex ].Content.IsValid() )
- {
- TSharedPtr< SVerticalBox > Box;
- FullTipContent =
- SNew(SBox)
- .Padding(DocumentationMargin)
- [
- SAssignNew(Box, SVerticalBox)
- + SVerticalBox::Slot()
- .HAlign(HAlign_Center)
- .AutoHeight()
- [
- Excerpts[ExcerptIndex].Content.ToSharedRef()
- ]
- ];
- FString* FullDocumentationLink = Excerpts[ ExcerptIndex ].Variables.Find( TEXT("ToolTipFullLink") );
- if ( FullDocumentationLink != NULL && !FullDocumentationLink->IsEmpty() )
- {
- struct Local
- {
- static void OpenLink( FString Link )
- {
- if (!IDocumentation::Get()->Open(Link, FDocumentationSourceInfo(TEXT("rich_tooltips"))))
- {
- FNotificationInfo Info( NSLOCTEXT("SToolTip", "FailedToOpenLink", "Failed to Open Link") );
- FSlateNotificationManager::Get().AddNotification(Info);
- }
- }
- };
- Box->AddSlot()
- .HAlign( HAlign_Center )
- .AutoHeight()
- [
- SNew( SHyperlink )
- .Text( NSLOCTEXT( "SToolTip", "GoToFullDocsLinkMessage", "see full documentation" ) )
- .TextStyle( &HyperlinkTextStyleInfo )
- .UnderlineStyle( &HyperlinkButtonStyleInfo )
- .OnNavigate_Static( &Local::OpenLink, *FullDocumentationLink )
- ];
- }
- if ( GetDefault<UEditorPerProjectUserSettings>()->bDisplayDocumentationLink && FSlateApplication::Get().SupportsSourceAccess() )
- {
- struct Local
- {
- static void EditSource( FString Link, int32 LineNumber )
- {
- ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
- SourceCodeAccessModule.GetAccessor().OpenFileAtLine(Link, LineNumber);
- }
- };
- Box->AddSlot()
- .AutoHeight()
- .HAlign( HAlign_Center )
- [
- SNew( SHyperlink )
- .Text( NSLOCTEXT( "SToolTip", "EditDocumentationMessage_Edit", "edit" ) )
- .TextStyle( &HyperlinkTextStyleInfo )
- .UnderlineStyle( &HyperlinkButtonStyleInfo )
- .OnNavigate_Static(&Local::EditSource, FPaths::ConvertRelativePathToFull(FExtDocumentationLink::ToSourcePath(DocumentationLink, FInternationalization::Get().GetCurrentCulture())), Excerpts[ExcerptIndex].LineNumber)
- ];
- }
- }
- }
- }
- FReply SExtDocumentationToolTip::ReloadDocumentation()
- {
- SimpleTipContent.Reset();
- FullTipContent.Reset();
- ConstructSimpleTipContent();
- if ( DocumentationPage.IsValid() )
- {
- DocumentationPage->Reload();
- if ( DocumentationPage->HasExcerpt( ExcerptName ) )
- {
- ConstructFullTipContent();
- }
- }
- return FReply::Handled();
- }
- void SExtDocumentationToolTip::Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime )
- {
- const FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys();
- const bool NeedsUpdate = IsDisplayingDocumentationLink != GetDefault<UEditorPerProjectUserSettings>()->bDisplayDocumentationLink;
- if ( !IsShowingFullTip && (AlwaysShowFullToolTip || (!AlwaysShowFullToolTip && ModifierKeys.IsAltDown() && ModifierKeys.IsControlDown())) )
- {
- if ( !FullTipContent.IsValid() && DocumentationPage.IsValid() && DocumentationPage->HasExcerpt( ExcerptName ) )
- {
- ConstructFullTipContent();
- }
- else if ( GetDefault<UEditorPerProjectUserSettings>()->bDisplayDocumentationLink )
- {
- ReloadDocumentation();
- }
- if ( FullTipContent.IsValid() )
- {
- WidgetContent->SetContent( FullTipContent.ToSharedRef() );
- IsShowingFullTip = true;
- // Analytics event
- if (FEngineAnalytics::IsAvailable())
- {
- TArray<FAnalyticsEventAttribute> Params;
- Params.Add(FAnalyticsEventAttribute(TEXT("Page"), DocumentationLink));
- Params.Add(FAnalyticsEventAttribute(TEXT("Excerpt"), ExcerptName));
- FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.Documentation.FullTooltipShown"), Params);
- }
- }
- }
- else if ( ( IsShowingFullTip || NeedsUpdate ) && !AlwaysShowFullToolTip && ( !ModifierKeys.IsAltDown() || !ModifierKeys.IsControlDown() ) )
- {
- if ( NeedsUpdate )
- {
- ReloadDocumentation();
- IsDisplayingDocumentationLink = GetDefault<UEditorPerProjectUserSettings>()->bDisplayDocumentationLink;
- }
- WidgetContent->SetContent( SimpleTipContent.ToSharedRef() );
- IsShowingFullTip = false;
- }
- }
- bool SExtDocumentationToolTip::IsInteractive() const
- {
- const FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys();
- return ( DocumentationPage.IsValid() && ModifierKeys.IsAltDown() && ModifierKeys.IsControlDown() );
- }
- #ifdef EXT_DOC_NAMESPACE
- #undef EXT_DOC_NAMESPACE
- #endif
|