// Icon Studio - Mathew Simon

#include "SIconStudioTab.h"

#include "Framework/Docking/TabManager.h"
#include "Modules/ModuleManager.h"
#include "Styling/AppStyle.h"
#include "ToolMenus.h"
#include "Widgets/Docking/SDockTab.h"
#include "WorkspaceMenuStructure.h"
#include "WorkspaceMenuStructureModule.h"

#define LOCTEXT_NAMESPACE "IconStudio"

namespace IconStudioModuleLocal
{
	/** Identifiant de l'onglet. Sert aussi de cle a la disposition sauvegardee. */
	static const FName StudioTabName(TEXT("IconStudio"));

	TSharedRef<SDockTab> SpawnStudioTab(const FSpawnTabArgs& Args)
	{
		return SNew(SDockTab)
			.TabRole(ETabRole::NomadTab)
			[
				SNew(SIconStudioTab)
			];
	}

	void OpenStudio()
	{
		// TryInvokeTab remet au premier plan l'onglet deja ouvert au lieu d'en
		// creer un second, et le rouvre a l'endroit ou l'utilisateur l'avait
		// docke la derniere fois.
		FGlobalTabmanager::Get()->TryInvokeTab(StudioTabName);
	}
}

/**
 * Le module pose le point d'entree de l'outil : l'onglet lui-meme, un bouton
 * dans la barre d'outils et une entree dans le menu Tools.
 *
 * Le reste s'enregistre tout seul -- le sous-systeme est instancie par le
 * moteur, les reglages apparaissent dans Project Settings grace a
 * UDeveloperSettings.
 */
class FIconStudioModule : public IModuleInterface
{
public:
	virtual void StartupModule() override
	{
		using namespace IconStudioModuleLocal;

		FGlobalTabmanager::Get()
			->RegisterNomadTabSpawner(StudioTabName, FOnSpawnTab::CreateStatic(&SpawnStudioTab))
			.SetDisplayName(LOCTEXT("IconStudioLabel", "Icon Studio"))
			.SetTooltipText(LOCTEXT("IconStudioTooltip", "Render item icons from a preset: preview, transparent background, batch over DataAssets."))
			.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), TEXT("ClassIcon.Texture2D")))
			// Le range dans Window > Tools, avec les autres outils de l'editeur.
			.SetGroup(WorkspaceMenu::GetMenuStructure().GetToolsCategory());

		// Le systeme de menus n'est pas forcement pret quand un module de plugin
		// demarre : ce rappel est la seule facon fiable d'etendre un menu, qu'on
		// soit charge avant ou apres l'editeur de niveau.
		UToolMenus::RegisterStartupCallback(
			FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &FIconStudioModule::RegisterMenus));
	}

	virtual void ShutdownModule() override
	{
		UToolMenus::UnRegisterStartupCallback(this);
		UToolMenus::UnregisterOwner(this);

		if (FSlateApplication::IsInitialized())
		{
			FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(IconStudioModuleLocal::StudioTabName);
		}
	}

private:
	void RegisterMenus()
	{
		// Tout ce qui est enregistre sous ce proprietaire part d'un bloc au
		// dechargement du module : sans lui, un rechargement a chaud laisserait
		// un bouton mort dans la barre d'outils.
		FToolMenuOwnerScoped OwnerScoped(this);

		const FSlateIcon Icon(FAppStyle::GetAppStyleSetName(), TEXT("ClassIcon.Texture2D"));
		const FText Label = LOCTEXT("IconStudioLabel", "Icon Studio");
		const FText Tooltip = LOCTEXT("IconStudioTooltip", "Render item icons from a preset: preview, transparent background, batch over DataAssets.");
		const FUIAction Action(FExecuteAction::CreateStatic(&IconStudioModuleLocal::OpenStudio));

		if (UToolMenu* ToolsMenu = UToolMenus::Get()->ExtendMenu(TEXT("LevelEditor.MainMenu.Tools")))
		{
			FToolMenuSection& Section = ToolsMenu->FindOrAddSection(
				TEXT("IconStudio"), LOCTEXT("IconStudioSection", "Icon Studio"));

			Section.AddMenuEntry(TEXT("OpenIconStudio"), Label, Tooltip, Icon, Action);
		}

		// Section "User" de la barre d'outils : l'emplacement prevu par le
		// moteur pour les outils maison, a droite des boutons natifs.
		if (UToolMenu* Toolbar = UToolMenus::Get()->ExtendMenu(TEXT("LevelEditor.LevelEditorToolBar.User")))
		{
			FToolMenuSection& Section = Toolbar->FindOrAddSection(TEXT("IconStudio"));

			Section.AddEntry(FToolMenuEntry::InitToolBarButton(
				TEXT("OpenIconStudio"), Action, Label, Tooltip, Icon));
		}
	}
};

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(FIconStudioModule, IconStudio);
