| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.#include "Documentation.h"#include "Misc/Paths.h"#include "Styling/CoreStyle.h"#include "Widgets/SToolTip.h"#include "Misc/MessageDialog.h"#include "HAL/FileManager.h"#include "Misc/CommandLine.h"#include "Dialogs/Dialogs.h"#include "SDocumentationAnchor.h"#include "UDNParser.h"#include "DocumentationPage.h"#include "DocumentationLink.h"#include "SExtDocumentationToolTip.h"#include "Interfaces/IAnalyticsProvider.h"#include "EngineAnalytics.h"#include "DocumentationLink.h"using namespace EXT_DOC_NAMESPACE;#define LOCTEXT_NAMESPACE "DocumentationActor"TSharedRef< IDocumentation > FExtDocumentation::Create() {	return MakeShareable( new FExtDocumentation() );}FExtDocumentation::FExtDocumentation() {}FExtDocumentation::~FExtDocumentation() {}bool FExtDocumentation::OpenHome(FDocumentationSourceInfo Source, const FString& BaseUrlId) const{	return Open(TEXT("%ROOT%"), Source, BaseUrlId);}bool FExtDocumentation::OpenHome(const FCultureRef& Culture, FDocumentationSourceInfo Source, const FString& BaseUrlId) const{	return Open(TEXT("%ROOT%"), Culture, Source, BaseUrlId);}bool FExtDocumentation::OpenAPIHome(FDocumentationSourceInfo Source) const{	FString Url;	FUnrealEdMisc::Get().GetURL(TEXT("APIDocsURL"), Url, true);	if (!Url.IsEmpty())	{		FUnrealEdMisc::Get().ReplaceDocumentationURLWildcards(Url, FInternationalization::Get().GetCurrentCulture());		FPlatformProcess::LaunchURL(*Url, nullptr, nullptr);		return true;	}	return false;}bool FExtDocumentation::Open(const FString& Link, FDocumentationSourceInfo Source, const FString& BaseUrlId) const{	FString DocumentationUrl;	// Warn the user if they are opening a URL	if (Link.StartsWith(TEXT("http")) || Link.StartsWith(TEXT("https")))	{		FText Message = LOCTEXT("OpeningURLMessage", "You are about to open an external URL. This will open your web browser. Do you want to proceed?");		FText URLDialog = LOCTEXT("OpeningURLTitle", "Open external link");		FSuppressableWarningDialog::FSetupInfo Info(Message, URLDialog, "SuppressOpenURLWarning");		Info.ConfirmText = LOCTEXT("OpenURL_yes", "Yes");		Info.CancelText = LOCTEXT("OpenURL_no", "No");		FSuppressableWarningDialog OpenURLWarning(Info);		if (OpenURLWarning.ShowModal() == FSuppressableWarningDialog::Cancel)		{			return false;		}		else		{			FPlatformProcess::LaunchURL(*Link, nullptr, nullptr);			return true;		}	}	if (!FParse::Param(FCommandLine::Get(), TEXT("testdocs")))	{		FString OnDiskPath = FExtDocumentationLink::ToFilePath(Link);		if (IFileManager::Get().FileSize(*OnDiskPath) != INDEX_NONE)		{			DocumentationUrl = FExtDocumentationLink::ToFileUrl(Link, Source);		}	}		if (DocumentationUrl.IsEmpty())	{		// When opening a doc website we always request the most ideal culture for our documentation.		// The DNS will redirect us if necessary.		DocumentationUrl = FExtDocumentationLink::ToUrl(Link, Source, BaseUrlId);	}	if (!DocumentationUrl.IsEmpty())	{		FPlatformProcess::LaunchURL(*DocumentationUrl, NULL, NULL);	}	if (!DocumentationUrl.IsEmpty() && FEngineAnalytics::IsAvailable())	{		FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.Documentation"), TEXT("OpenedPage"), Link);	}	return !DocumentationUrl.IsEmpty();}bool FExtDocumentation::Open(const FString& Link, const FCultureRef& Culture, FDocumentationSourceInfo Source, const FString& BaseUrlId) const{	FString DocumentationUrl;	if (!FParse::Param(FCommandLine::Get(), TEXT("testdocs")))	{		FString OnDiskPath = FExtDocumentationLink::ToFilePath(Link, Culture);		if (IFileManager::Get().FileSize(*OnDiskPath) != INDEX_NONE)		{			DocumentationUrl = FExtDocumentationLink::ToFileUrl(Link, Culture, Source);		}	}	if (DocumentationUrl.IsEmpty())	{		DocumentationUrl = FExtDocumentationLink::ToUrl(Link, Culture, Source, BaseUrlId);	}	if (!DocumentationUrl.IsEmpty())	{		FPlatformProcess::LaunchURL(*DocumentationUrl, NULL, NULL);	}	if (!DocumentationUrl.IsEmpty() && FEngineAnalytics::IsAvailable())	{		FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.Documentation"), TEXT("OpenedPage"), Link);	}	return !DocumentationUrl.IsEmpty();}TSharedRef< SWidget > FExtDocumentation::CreateAnchor(const TAttribute<FString>& Link, const FString& PreviewLink, const FString& PreviewExcerptName, const TAttribute<FString>& BaseUrlId) const{	return SNew( SExtDocumentationAnchor )		.Link(Link)		.PreviewLink(PreviewLink)		.PreviewExcerptName(PreviewExcerptName)		.BaseUrlId(BaseUrlId);}TSharedRef< IDocumentationPage > FExtDocumentation::GetPage( const FString& Link, const TSharedPtr< FParserConfiguration >& Config, const FDocumentationStyle& Style ){	TSharedPtr< IDocumentationPage > Page;	const TWeakPtr< IDocumentationPage >* ExistingPagePtr = LoadedPages.Find( Link );	if ( ExistingPagePtr != NULL )	{		const TSharedPtr< IDocumentationPage > ExistingPage = ExistingPagePtr->Pin();		if ( ExistingPage.IsValid() )		{			Page = ExistingPage;		}	}	if ( !Page.IsValid() )	{		Page = FExtDocumentationPage::Create( Link, FExtUDNParser::Create( Config, Style ) );		LoadedPages.Add( Link, TWeakPtr< IDocumentationPage >( Page ) );	}	return Page.ToSharedRef();}bool FExtDocumentation::PageExists(const FString& Link) const{	const TWeakPtr< IDocumentationPage >* ExistingPagePtr = LoadedPages.Find(Link);	if (ExistingPagePtr != NULL)	{		return true;	}	const FString SourcePath = FExtDocumentationLink::ToSourcePath(Link);	return FPaths::FileExists(SourcePath);}bool FExtDocumentation::PageExists(const FString& Link, const FCultureRef& Culture) const{	const TWeakPtr< IDocumentationPage >* ExistingPagePtr = LoadedPages.Find(Link);	if (ExistingPagePtr != NULL)	{		return true;	}	const FString SourcePath = FExtDocumentationLink::ToSourcePath(Link, Culture);	return FPaths::FileExists(SourcePath);}const TArray < FString >& EXT_DOC_NAMESPACE::FExtDocumentation::GetSourcePaths() const{	return SourcePaths;}TSharedRef< class SToolTip > FExtDocumentation::CreateToolTip(const TAttribute<FText>& Text, const TSharedPtr<SWidget>& OverrideContent, const FString& Link, const FString& ExcerptName) const{	TSharedPtr< SExtDocumentationToolTip > DocToolTip;	if ( !Text.IsBound() && Text.Get().IsEmpty() )	{		return SNew( SToolTip );	}	// hack: use OverrideContent as flag to always show full tooltip	if (OverrideContent.IsValid())	{		SAssignNew(DocToolTip, SExtDocumentationToolTip)			.Text(Text)			.DocumentationLink(Link)			.ExcerptName(ExcerptName)			.AlwaysShowFullToolTip(true);	}	else	{		SAssignNew( DocToolTip, SExtDocumentationToolTip )		.Text( Text )		.DocumentationLink( Link )		.ExcerptName( ExcerptName );	}		return SNew( SToolTip )		.IsInteractive( DocToolTip.ToSharedRef(), &SExtDocumentationToolTip::IsInteractive )		// Emulate text-only tool-tip styling that SToolTip uses when no custom content is supplied.  We want documentation tool-tips to 		// be styled just like text-only tool-tips		.BorderImage( FCoreStyle::Get().GetBrush("ToolTip.BrightBackground") )		.TextMargin(FMargin(11.0f))		[			DocToolTip.ToSharedRef()		];}TSharedRef< class SToolTip > FExtDocumentation::CreateToolTip(const TAttribute<FText>& Text, const TSharedRef<SWidget>& OverrideContent, const TSharedPtr<SVerticalBox>& DocVerticalBox, const FString& Link, const FString& ExcerptName) const{	TSharedRef<SExtDocumentationToolTip> DocToolTip =		SNew(SExtDocumentationToolTip)		.Text(Text)		.DocumentationLink(Link)		.ExcerptName(ExcerptName)		.AddDocumentation(false)		.DocumentationMargin(7)		[			OverrideContent		];	if (DocVerticalBox.IsValid())	{		DocToolTip->AddDocumentation(DocVerticalBox);	}	return SNew(SToolTip)		.IsInteractive(DocToolTip, &SExtDocumentationToolTip::IsInteractive)		// Emulate text-only tool-tip styling that SToolTip uses when no custom content is supplied.  We want documentation tool-tips to 		// be styled just like text-only tool-tips		.BorderImage( FCoreStyle::Get().GetBrush("ToolTip.BrightBackground") )		.TextMargin(FMargin(11.0f))		[			DocToolTip		];}bool FExtDocumentation::RegisterBaseUrl(const FString& Id, const FString& Url){	if (!Id.IsEmpty() && !Url.IsEmpty())	{		if (!RegisteredBaseUrls.Contains(Id))		{			RegisteredBaseUrls.Add(Id, Url);			return true;		}		//UE_LOG(LogDocumentation, Warning, TEXT("Could not register documentation base URL with ID: %s. This ID is already in use."), *Id);		return false;	}	return false;}FString FExtDocumentation::GetBaseUrl(const FString& Id) const{	if (!Id.IsEmpty())	{		const FString* BaseUrl = RegisteredBaseUrls.Find(Id);		if (BaseUrl != NULL && !BaseUrl->IsEmpty())		{			return *BaseUrl;		}		//UE_LOG(LogDocumentation, Warning, TEXT("Could not resolve base URL with ID: %s. It may not have been registered."), *Id);	}	FString DefaultUrl;	FUnrealEdMisc::Get().GetURL(TEXT("DocumentationURL"), DefaultUrl, true);	return DefaultUrl;}bool FExtDocumentation::RegisterRedirect(const FName& Owner, const FDocumentationRedirect& Redirect){	return RedirectRegistry.Register(Owner, Redirect);}void FExtDocumentation::UnregisterRedirects(const FName& Owner){	RedirectRegistry.UnregisterAll(Owner);}#undef LOCTEXT_NAMESPACE#ifdef EXT_DOC_NAMESPACE#undef EXT_DOC_NAMESPACE#endif
 |